Creating directories during a copy using IFileOperation(使用 IFileOperation 在复制期间创建目录)
问题描述
使用 Stephen Toub 的 C# 的 IFileOperation 包装器(link),到目前为止一直运行良好.现在我正在尝试复制以从网络位置收集文件,每个网络位置到它自己的子目录中.
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.
\FOOdata 到 C:gatherFoo_data\BARmanagecurrent 到 C:gatherarmanage
等等.问题出在 FileOperation.CopyItem 中.一定是因为目标目录还不存在——IFileOperation 会在复制过程中创建它,对吧?我使用了 another question 中的技术并更改了 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 );
}
}
我将 Debug.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 for a nonexistent file"吗?我怀疑我需要在其中获取 SFGAO_FOLDER,因为我正在尝试为不存在的 directory 创建一个 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.
- 编写一个实现
IFileSystemBindData的COM兼容类. - 分配一个
WIN32_FIND_DATA结构并设置它的dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY.(其他成员在这里无关紧要,据我经过一些测试后得知.) - 创建您的
IFileSystemBindData类的实例. - 将您的
WIN32_FIND_DATA对象传递给IFileSystemBindData::SetFindData. - 创建一个
IBindCtx的实例. - 使用
STR_FILE_SYS_BIND_DATA的参数调用它的IBindCtx::RegisterObjectParam(#defined asL"File System Bind Data") 和您的IFileSystemBindData对象. - 使用要创建的目录的路径名和您的
IBindCtx对象调用SHCreateItemFromParsingName.
- Write a COM-compatible class that implements
IFileSystemBindData. - Allocate a
WIN32_FIND_DATAstructure 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
IFileSystemBindDataclass. - Pass your
WIN32_FIND_DATAobject toIFileSystemBindData::SetFindData. - Create an instance of
IBindCtx. - Call its
IBindCtx::RegisterObjectParamwith arguments ofSTR_FILE_SYS_BIND_DATA(#defined asL"File System Bind Data") and yourIFileSystemBindDataobject. - Call
SHCreateItemFromParsingNamewith the pathname of the directory to create, and yourIBindCtxobject.
它有效.binding-context 对象告诉 SHCreateItemFromParsingName 不要查询文件系统,而只使用它给出的内容.我让 IFileOperation 将文件复制到新的且命名巧妙的目录 D:SomePathThatDidNotPreviousExist 中,它创建了所有沿途有七个目录.据推测,同样的技术可用于为任何不存在的文件系统对象创建 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:SomePathThatDidNotPreviouslyExist, 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 在复制期间创建目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:使用 IFileOperation 在复制期间创建目录
基础教程推荐
- 从 VS 2017 .NET Core 项目的发布目录中排除文件 2022-01-01
- 是否可以在 asp classic 和 asp.net 之间共享会话状态 2022-01-01
- 首先创建代码,多对多,关联表中的附加字段 2022-01-01
- JSON.NET 中基于属性的类型解析 2022-01-01
- 经典 Asp 中的 ResolveUrl/Url.Content 等效项 2022-01-01
- 如何动态获取文本框中datagridview列的总和 2022-01-01
- 错误“此流不支持搜索操作"在 C# 中 2022-01-01
- 将事件 TextChanged 分配给表单中的所有文本框 2022-01-01
- 在 VS2010 中的 Post Build 事件中将 bin 文件复制到物 2022-01-01
- 全局 ASAX - 获取服务器名称 2022-01-01
