使用IFileOperation一个复制过程中创建的目录 [英] Creating directories during a copy using IFileOperation

查看:528
本文介绍了使用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.


  1. 写COM兼容的类,它实现 IFileSystemBindData

  2. 分配一个 WIN32_FIND_DATA 结构,并设置其 dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY 。 (其他成员是这里无关紧要,因为据我一些测试后说。)

  3. 创建您的 IFileSystemBindData 类的一个实例

  4. 通过你的 WIN32_FIND_DATA 对象 IFileSystemBindData :: SetFindData

  5. 创建的实例 IBindCtx

  6. 调用它的 IBindCtx :: RegisterObjectParam STR_FILE_SYS_BIND_DATA 的参数(的#define D为→ 文件系统将数据绑定)和你的 IFileSystemBindData 对象。

  7. 呼叫 SHCreateItemFromParsingName 与目录的路径名来创建,你的 IBindCtx 对象。

  1. Write a COM-compatible class that implements IFileSystemBindData.
  2. Allocate a WIN32_FIND_DATA structure and set its dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY. (The other members are irrelevant here, as far as I can tell after some testing.)
  3. Create an instance of your IFileSystemBindData class.
  4. Pass your WIN32_FIND_DATA object to IFileSystemBindData::SetFindData.
  5. Create an instance of IBindCtx.
  6. Call its IBindCtx::RegisterObjectParam with arguments of STR_FILE_SYS_BIND_DATA (#defined as L"File System Bind Data") and your IFileSystemBindData object.
  7. Call SHCreateItemFromParsingName with the pathname of the directory to create, and your IBindCtx 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆