2012-08-10 16 views
5

Utilizzo del wrapper IFileOperation di Stephen Toub per C# (link), che ha funzionato bene fino ad ora. Ora sto cercando di fare una copia per raccogliere i file dalle posizioni di rete, ciascuna posizione di rete nella propria sottodirectory.Creazione di directory durante una copia utilizzando IFileOperation

\\FOO\data in C:\gather\Foo_data
\\BAR\manage\current in C:\gather\bar\manage

E così via. Il problema è in FileOperation.CopyItem. Deve essere perché la directory di destinazione non esiste ancora- IFileOperation la creerà durante la copia, giusto? Ho usato la tecnica da another question e cambiato Toub di FileOperation.CreateShellItem a questo:

private static ComReleaser<IShellItem> CreateShellItem(string path) 
{ 
    try 
    { 
     return new ComReleaser<IShellItem>((IShellItem)SHCreateItemFromParsingName(path, null, ref _shellItemGuid)); 
    } 
    catch (FileNotFoundException) 
    { 
     IntPtr pidl = SHSimpleIDListFromPath(path); 
     IShellItem isi = (IShellItem)SHCreateItemFromIDList(pidl, ref _shellItemGuid); 
     Marshal.FreeCoTaskMem(pidl); 
     System.Diagnostics.Debug.WriteLine("Shell item: " + isi.GetDisplayName(SIGDN.DesktopAbsoluteParsing)); 
     return new ComReleaser<IShellItem>(isi); 
    } 
} 

ho bloccato il Debug.WriteLine in là per controllare che sta funzionando, e sembra funzionare bene; scrive il percorso di nuovo.

Ma getta un ArgumentException e non riesco a capire perché. Non sto facendo il "IShellItem per un file inesistente" correttamente? Ho il sospetto che ho bisogno di ottenere SFGAO_FOLDER lì, poiché sto cercando di creare un IShellItem per una directory inesistente , non file, ma come?

risposta

6

Dopo un sacco di ricerche su Google e coding questo fine settimana (che fine settimana di festa sfrenata), ho trovato una soluzione.

  1. Scrivere una classe compatibile con COM che implementa IFileSystemBindData.
  2. Assegnare una struttura WIN32_FIND_DATA e impostarne dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY. (Gli altri membri sono irrilevanti qui, per quanto posso dire dopo alcuni test.)
  3. Creare un'istanza della classe IFileSystemBindData.
  4. Passa l'oggetto WIN32_FIND_DATA a IFileSystemBindData::SetFindData.
  5. Creare un'istanza di IBindCtx.
  6. chiamare il suo IBindCtx::RegisterObjectParam con argomenti di STR_FILE_SYS_BIND_DATA (#define d come L"File System Bind Data") e il vostro IFileSystemBindData oggetto.
  7. Chiama il SHCreateItemFromParsingName con il nome percorso della directory da creare e l'oggetto IBindCtx.

Funziona. L'oggetto contesto vincolante dice a SHCreateItemFromParsingName di non interrogare il filesystem e di usare solo ciò che viene dato. Ho ottenuto IFileOperation per copiare un file nella nuova directory con nome intelligente D:\Some\Path\That\Did\Not\Previously\Exist e ha creato tutte e sette le directory lungo la strada. Presumibilmente, questa stessa tecnica potrebbe essere utilizzata per creare un IShellItem per qualsiasi oggetto file system inesistente, a seconda di cosa si è inserito in dwFileAttributes.

Ma è brutto. Spero ci sia un modo migliore. La mia sperimentazione di codifica era in C++; ora per scrivere gli oggetti di interoperabilità COM per farlo di nuovo in C#. O forse sarà più semplice lanciare il progetto e ricominciare da capo in C++.

Problemi correlati