来自IShellDispatch的Folder.CopyHere()默默地无法解压缩大部分Zip文件,但仅当文件在DVD上时才能解压缩

时间:2017-12-18 19:36:26

标签: com unzip windows-shell dvd

我的应用程序(Endless OS installer for Windows)使用IShellDispatch (provided by Shell32.dll)上的方法来提取Zip文件(example)。在各种操作模式中,该文件可以从因特网下载到固定盘;在USB记忆棒上的exFAT文件系统上;或者在ISO 9660(带有Joliet扩展名)图像中,可以作为虚拟驱动器安装,也可以写入DVD。在所有情况下,但最后,提取Zip文件工作;但是当Zip文件在DVD上时,在目标目录中创建的所有内容都是归档中第一个文件的目录结构(EFI\BOOT\)(EFI\BOOT\bootx64.efi);该文件或该目录或任何其他目录中的任何其他文件都不会被提取。在任何其他介质上使用完全相同的Zip文件 - 包括将ISO插入VirtualBox虚拟光驱 - 问题就会消失。

我第一次看到这个问题的原始C ++代码是here。它看起来像这样(删除了错误处理,因为我的测试中所有方法都返回成功的HRESULT,并且在屏蔽错误消息的情况下也删除了FOF_NO_UI):

void UnpackZip(const CComBSTR source, const CComBSTR dest) {
    CComPtr<IShellDispatch>    pISD;
    CComPtr<Folder>            pToFolder, pFromFolder;
    CComPtr<FolderItems>       folderItems;

    CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch,
        (void **)&pISD);
    pISD->NameSpace(CComVariant(dest), &pToFolder);
    pISD->NameSpace(CComVariant(source), &pFromFolder);
    pFromFolder->Items(&folderItems);
    pToFolder->CopyHere(CComVariant(folderItems), CComVariant(0));
}

我可以通过尝试从Windows资源管理器GUI(不报告任何错误)解压缩Zip文件,并在PowerShell中运行以下内容来重现此问题,因此我有理由相信它不是我的应用程序错误的代码:

PS> $shell = new-object -ComObject shell.application
PS> $zip = $shell.NameSpace("D:\endless\eos-eos3.3-amd64-amd64.171122-232702.base.boot.zip")
PS> $target = $shell.NameSpace("C:\test")
PS> $target.CopyHere($zip.items())

如果我显式迭代Zip文件中的顶级文件夹,如下所示,则会提取每个文件夹中的一些但不是所有文件(EFI\BOOT\中仍然没有):

PS> foreach ($item in $zip.items()) { $target.CopyHere($item) }

如果我明确选择了未解包的第一个文件,则不会引发错误:

PS> $item = $zip.items().Item(0).GetFolder().Items().Item(0).GetFolder().Items().item(0);
PS> $item
Application  : System.__ComObject
Parent       : System.__ComObject
Name         : bootx64.efi
Path         :
GetLink      :
GetFolder    :
IsLink       : False
IsFolder     : False
IsFileSystem : False
IsBrowsable  : False
ModifyDate   : 22/11/2017 23:33:56
Size         : 1157984
Type         : EFI File
PS> $target.CopyHere($item)

但它仍未解包到$target。 DVD驱动器甚至没有旋转!

如果我将完全相同的Zip文件复制到固定驱动器 - 或者将DVD ISO作为虚拟磁盘安装,无论是在Windows内,还是从外部通过VirtualBox VM运行Windows - 一切正常。当存档确实在物理DVD上时,会出现的问题。我从各种硬件用户那里收到了很多关于这个问题的报告,所以它不是我的DVD驱动器或笔记本电脑。我个人只在Windows 10上测试和复制它(至少建立14393和15063);我不确定它是否可以在较旧的Windows版本上重现,但由于Windows 10是此应用程序用户最常用的版本,因此这是否适用于旧版本。

未解包的文件都是以.efi(EFI可执行文件)结尾的文件和以.mod结尾的文件(传统的BIOS GRUB模块)。这完全是确定性的。但是,我很难理解为什么shell会对某些文件不喜欢,只有当存档在DVD上时才会这样。

我的应用程序可以通过在解压缩之前将Zip文件复制到硬盘来解决此问题。但问题仍然存在:为什么会发生这种情况?在更高的层次上:如果没有在调试器中逐步编译已编译的Shell32.dll代码,我怎么能诊断出错了什么?

0 个答案:

没有答案