2012-08-10 12 views
5

का उपयोग करके प्रतिलिपि के दौरान निर्देशिका बनाना C# (link) के लिए स्टीफन टब के IFileOperation wrapper का उपयोग करना, जो अब तक अच्छी तरह से काम कर रहा है। अब मैं नेटवर्क स्थानों से फ़ाइलों को इकट्ठा करने के लिए एक प्रतिलिपि करने की कोशिश कर रहा हूं, प्रत्येक नेटवर्क स्थान अपनी उपनिर्देशिका में है।IFileOperation

C:\gather\bar\manage

और इसी में C:\gather\Foo_data
\\BAR\manage\current में \\FOO\data। समस्या FileOperation.CopyItem में है। ऐसा इसलिए होना चाहिए क्योंकि गंतव्य निर्देशिका अभी तक मौजूद नहीं है- IFileOperation प्रतिलिपि के दौरान इसे बनाएगी, है ना? मैं another question से तकनीक का इस्तेमाल किया है और इसे बदला Toub के FileOperation.CreateShellItem यह करने के लिए:

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); 
    } 
} 

मैं जाँच करने के लिए है कि यह काम कर रहा है वहाँ में Debug.WriteLine अटक, और यह ठीक काम कर रहा है; यह पथ वापस लिखता है।

लेकिन IFileOperation.CopyItemArgumentException फेंकता है, और मैं यह नहीं समझ सकता कि क्यों। क्या मैं "IShellItem एक गैर-फाइल फ़ाइल के लिए" सही तरीके से नहीं कर रहा हूं? मुझे संदेह है कि मुझे वहां SFGAO_FOLDER प्राप्त करने की आवश्यकता है, क्योंकि मैं को किसी भी 0xनिर्देशिका के लिए फ़ाइल नहीं, बल्कि कैसे?

उत्तर

6

इस सप्ताह के अंत में बहुत सारे गुगलिंग और कोडिंग प्रयोग के बाद (क्या एक जंगली पार्टी सप्ताहांत), मुझे एक समाधान मिला।

  1. एक COM- संगत वर्ग लिखें जो IFileSystemBindData लागू करता है।
  2. WIN32_FIND_DATA संरचना आवंटित करें और इसकी dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY सेट करें। (अन्य सदस्य यहां अप्रासंगिक हैं, जहां तक ​​मैं कुछ परीक्षण के बाद बता सकता हूं।)
  3. अपने IFileSystemBindData कक्षा का एक उदाहरण बनाएं।
  4. ऑब्जेक्ट IFileSystemBindData::SetFindData पर ऑब्जेक्ट पास करें।
  5. IBindCtx का एक उदाहरण बनाएं।
  6. की STR_FILE_SYS_BIND_DATA (L"File System Bind Data" रूप #define घ) और अपने IFileSystemBindData वस्तु तर्क के साथ अपनी IBindCtx::RegisterObjectParam पर कॉल करें।
  7. निर्देशिका बनाने के पथनाम के साथ SHCreateItemFromParsingName पर कॉल करें, और IBindCtx ऑब्जेक्ट।

यह काम करता है। बाध्यकारी-संदर्भ वस्तु SHCreateItemFromParsingName बताती है कि फाइल सिस्टम से पूछताछ न करें, और केवल जो भी दिया गया है उसका उपयोग करें। मुझे IFileOperation को नई और चालाकी से नामित निर्देशिका D:\Some\Path\That\Did\Not\Previously\Exist में फ़ाइल कॉपी करने के लिए मिला, और इसने सभी सात निर्देशिकाएं बनाईं। संभवतः इस तकनीक को में डाले गए किसी भी मौजूदा फाइल सिस्टम ऑब्जेक्ट के लिए IShellItem बनाने के लिए उपयोग किया जा सकता है।

लेकिन यह बदसूरत है। मुझे उम्मीद है कि एक बेहतर तरीका है। मेरा कोडिंग प्रयोग सी ++ में था; अब सी # में फिर से करने के लिए COM इंटरऑप सामान लिखने के लिए। या शायद परियोजना को फेंकना और सी ++ में शुरू करना आसान होगा।