7

使用 Stephen Toub 的 C# 的 IFileOperation 包装器(链接),它一直运行良好,直到现在。现在我正在尝试复制以从网络位置收集文件,每个网络位置到它自己的子目录中。

\\FOO\dataC:\gather\Foo_data
\\BAR\manage\currentC:\gather\bar\manage

等等。问题出在FileOperation.CopyItem. 一定是因为目标目录还不存在——<code>IFileOperation 会在复制过程中创建它,对吧?我使用了另一个问题的技术并将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为不存在的目录而不是文件创建一个目录,但是如何?

4

1 回答 1

8

在这个周末(多么疯狂的派对周末)进行了大量的谷歌搜索和编码实验之后,我找到了一个解决方案。

  1. 编写一个与 COM 兼容的类来实现IFileSystemBindData.
  2. 分配一个WIN32_FIND_DATA结构并设置它的dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY. (其他成员在这里无关紧要,据我经过一些测试后得知。)
  3. 创建你的IFileSystemBindData类的一个实例。
  4. 将您的WIN32_FIND_DATA对象传递给IFileSystemBindData::SetFindData.
  5. 创建一个IBindCtx.
  6. 使用( d as ) 和您的对象IBindCtx::RegisterObjectParam的参数调用它。STR_FILE_SYS_BIND_DATA#defineL"File System Bind Data"IFileSystemBindData
  7. SHCreateItemFromParsingName使用要创建的目录的路径名和您的对象调用IBindCtx

有用。binding-context 对象告诉SHCreateItemFromParsingName不要查询文件系统,而只使用它给出的内容。我必须IFileOperation将一个文件复制到新的且命名巧妙的目录D:\Some\Path\That\Did\Not\Previously\Exist中,它一路上创建了所有七个目录。据推测,同样的技术可用于IShellItem为任何不存在的文件系统对象创建一个,具体取决于您放入的dwFileAttributes.

但它很丑。我希望有更好的方法。我的编码实验是在 C++ 中进行的。现在编写 COM 互操作的东西以在 C# 中再次执行此操作。或者,放弃项目并在 C++ 中重新开始可能会更容易。

于 2012-08-12T20:53:21.247 回答