使用IFileOperation一个复制过程中创建的目录 [英] Creating directories during a copy using IFileOperation
问题描述
使用C#的斯蒂芬Toub的IFileOperation包装(链接),这一直很好,直到如今。现在我试图做一个副本收集来自网络位置,每个网络位置到它自己的子目录中的文件。
Using Stephen Toub's IFileOperation wrapper for C# (link), which has been working well until now. Now I am trying to do a copy to gather files from network locations, each network location into its own subdirectory.
\\FOO\\ \\data
到 C:\gather\Foo_data
结果
\\BAR\\ \\manage\current
到 C:\gather\bar\manage
等。问题出在 FileOperation.CopyItem
。那一定是因为目标目录尚不存在 - IFileOperation
将在复制期间创建它,对吗?我使用的技术从另一个问题并改变Toub的 FileOperation.CreateShellItem
来的:
And so on. The problem is in FileOperation.CopyItem
. It must be because the destination directory doesn't exist yet—IFileOperation
will create it during the copy, right? I used the technique from another question and changed Toub's FileOperation.CreateShellItem
to this:
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 );
}
}
我坚持了调试。的WriteLine
在那里,以检查它的工作,它似乎是做工精细;回写出来的路径。
I stuck the Debug.WriteLine
in there to check that it's working, and it seems to be working fine; it writes the path back out.
但 IFileOperation.CopyItem
引发的ArgumentException
,我想不通为什么。我不能做了的IShellItem
为不存在的文件是否正确?我怀疑我需要获得 SFGAO_FOLDER
在那里,因为我想要创建一个的IShellItem
为一个不存在的目录,不是一个文件,而是如何?
But IFileOperation.CopyItem
throws an ArgumentException
, and I can't figure out why. Am I not doing the "IShellItem
for a nonexistent file" correctly? I suspect I need to get SFGAO_FOLDER
in there, since I am trying to create an IShellItem
for a nonexistent directory, not file, but how?
推荐答案
很多谷歌搜索和编码实验本周末之后(什么疯狂的派对周末),我找到了解决办法。
After a lot of Googling and coding experimentation this weekend (what a wild party weekend), I found a solution.
- 写COM兼容的类,它实现
IFileSystemBindData
。 - 分配一个
WIN32_FIND_DATA
结构,并设置其dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY
。 (其他成员是这里无关紧要,因为据我一些测试后说。) - 创建您的
IFileSystemBindData
类的一个实例 - 通过你的
WIN32_FIND_DATA
对象IFileSystemBindData :: SetFindData
。 - 创建的实例
IBindCtx
。 - 调用它的
IBindCtx :: RegisterObjectParam
与STR_FILE_SYS_BIND_DATA
的参数(的#define
D为→ 文件系统将数据绑定
)和你的IFileSystemBindData
对象。 - 呼叫
SHCreateItemFromParsingName
与目录的路径名来创建,你的IBindCtx
对象。
- Write a COM-compatible class that implements
IFileSystemBindData
. - Allocate a
WIN32_FIND_DATA
structure and set itsdwFileAttributes = FILE_ATTRIBUTE_DIRECTORY
. (The other members are irrelevant here, as far as I can tell after some testing.) - Create an instance of your
IFileSystemBindData
class. - Pass your
WIN32_FIND_DATA
object toIFileSystemBindData::SetFindData
. - Create an instance of
IBindCtx
. - Call its
IBindCtx::RegisterObjectParam
with arguments ofSTR_FILE_SYS_BIND_DATA
(#define
d asL"File System Bind Data"
) and yourIFileSystemBindData
object. - Call
SHCreateItemFromParsingName
with the pathname of the directory to create, and yourIBindCtx
object.
它的工作原理。结合上下文对象告诉 SHCreateItemFromParsingName
不是查询文件系统,而只是用它给了。我得到了 IFileOperation
将文件复制到新的和巧妙地命名的目录 D:\Some\Path\That\Did\ Not\Previously\Exist
,它创造了沿途的所有七个目录。据推测,这同样的技术可以被用来创建一个的IShellItem
任何不存在的文件系统对象,这取决于你把什么 dwFileAttributes
。
It works. The binding-context object tells SHCreateItemFromParsingName
not to query the filesystem, and just use what it's given. I got IFileOperation
to copy a file into the new and cleverly-named directory D:\Some\Path\That\Did\Not\Previously\Exist
, and it created all seven directories along the way. Presumably this same technique could be used to create an IShellItem
for any non-existent filesystem object, depending on what you put in dwFileAttributes
.
但它的丑陋。我希望有一个更好的办法。我的编码实验是用C ++;现在写的COM互操作的东西在C#中做一遍。或者,也许它会更容易抛出了项目,并在C ++中开始了。
But it's ugly. I hope there's a better way. My coding experimentation was in C++; now to write the COM interop stuff to do it again in C#. Or maybe it will be easier to throw out the project and start over in C++.
这篇关于使用IFileOperation一个复制过程中创建的目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!