C# .NET 4.0压缩空文件夹至Zip报错及无父目录实现疑问
问题解答
一、空文件夹压缩报错的原因
当你调用sourceFolder.Items()时,空文件夹的Items集合是空的——Shell的CopyHere方法无法处理空的项集合,因此抛出“Can't add empty folder to zip archive”错误。只有当集合中存在可复制的项(文件或子文件夹)时,这个调用才能正常执行。
二、压缩空文件夹且不包含父文件夹的实现方案
要实现压缩目标文件夹内的内容(含空文件夹场景)且不将目标文件夹本身作为根目录放入Zip,可以通过分情况处理的方式实现:
具体代码实现
internal void compressZip(string folderPath) { if (!Directory.Exists(folderPath)) { MessageBox.Show("Directory not exist: " + folderPath); return; } string zipPath = folderPath + ".zip"; // 初始化空Zip文件结构 byte[] startBuffer = { 80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; File.WriteAllBytes(zipPath, startBuffer); var shellAppType = Type.GetTypeFromProgID("Shell.Application"); var oShell = Activator.CreateInstance(shellAppType); var destinationFile = (Shell32.Folder)shellAppType.InvokeMember("NameSpace", System.Reflection.BindingFlags.InvokeMethod, null, oShell, new object[] { zipPath }); // 检查目标文件夹是否为空 var dirInfo = new DirectoryInfo(folderPath); bool isEmpty = dirInfo.GetFiles().Length == 0 && dirInfo.GetDirectories().Length == 0; if (isEmpty) { // 空文件夹场景:从父目录中获取当前空文件夹作为单独项复制 string parentFolderPath = Path.GetDirectoryName(folderPath); var parentFolder = (Shell32.Folder)shellAppType.InvokeMember("NameSpace", System.Reflection.BindingFlags.InvokeMethod, null, oShell, new object[] { parentFolderPath }); // 获取当前空文件夹的Shell项 var emptyFolderItem = parentFolder.ParseName(Path.GetFileName(folderPath)); destinationFile.CopyHere(emptyFolderItem, 4 | 16); } else { // 非空文件夹场景:复制内部所有项,避免带入父文件夹 var sourceFolder = (Shell32.Folder)shellAppType.InvokeMember("NameSpace", System.Reflection.BindingFlags.InvokeMethod, null, oShell, new object[] { folderPath }); destinationFile.CopyHere(sourceFolder.Items(), 4 | 16); } }
逻辑说明
- 空文件夹场景:通过父目录定位到当前空文件夹,将其作为单个项复制到Zip中,这样Zip内只会包含这个空文件夹,不会带上更高层级的父目录。
- 非空文件夹场景:继续使用
sourceFolder.Items()复制内部所有内容,确保Zip中只有目标文件夹内的内容,不包含目标文件夹本身。
补充提示
CopyHere方法是异步执行的,如果需要确保压缩完成后再进行后续操作,需要额外添加等待逻辑(比如循环检查Zip文件的大小变化或锁定状态)。
内容的提问来源于stack exchange,提问作者Sem
相关产品推荐
相关产品推荐

