使用Stephen Toub的C#(link)的IFileOperation包装器,直到现在一直运行良好。现在我正在尝试复制以从网络位置收集文件,将每个网络位置收集到其自己的子目录中。
\\FOO\data
加入C:\gather\Foo_data
\\BAR\manage\current
进入C:\gather\bar\manage
等等。问题出在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.CopyItem
会抛出ArgumentException
,我无法弄清楚原因。我没有正确地为“不存在的文件”执行“IShellItem
”吗?我怀疑我需要在那里获得SFGAO_FOLDER
,因为我正在尝试为不存在的目录创建IShellItem
,而不是文件,但是如何?
答案 0 :(得分:6)
经过本周末的大量谷歌搜索和编码实验(这是一个疯狂的派对周末),我找到了解决方案。
IFileSystemBindData
的COM兼容类。WIN32_FIND_DATA
结构并设置其dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY
。 (其他成员在这里是无关紧要的,据我测试一样。)IFileSystemBindData
班级的实例。WIN32_FIND_DATA
对象传递给IFileSystemBindData::SetFindData
。IBindCtx
。IBindCtx::RegisterObjectParam
(STR_FILE_SYS_BIND_DATA
d为#define
)和L"File System Bind Data"
对象的参数调用IFileSystemBindData
。SHCreateItemFromParsingName
对象调用IBindCtx
。有效。绑定上下文对象告诉SHCreateItemFromParsingName
不要查询文件系统,只使用它给出的内容。我得到IFileOperation
将文件复制到新的且名称巧妙的目录D:\Some\Path\That\Did\Not\Previously\Exist
中,并且沿途创建了所有七个目录。据推测,可以使用相同的技术为任何不存在的文件系统对象创建IShellItem
,具体取决于您在dwFileAttributes
中放置的内容。
但它很难看。我希望有更好的方法。我的编码实验是用C ++编写的;现在编写COM互操作的东西再用C#做。或者也许更容易抛出项目并重新开始用C ++。