【问题标题】:Creating directories during a copy using IFileOperation使用 IFileOperation 在复制期间创建目录
【发布时间】:2012-08-07 18:42:35
【问题描述】:

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

\\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,而不是文件,但是如何?

【问题讨论】:

    标签: c# com


    【解决方案1】:

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

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

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

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

    【讨论】:

    猜你喜欢
    • 2010-11-02
    • 2011-12-04
    • 1970-01-01
    • 2011-10-02
    • 1970-01-01
    • 1970-01-01
    • 2020-10-22
    • 1970-01-01
    • 2018-08-06
    相关资源
    最近更新 更多