LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

C#原生代码将zip压缩文件解压到指定目录,不需要借助第三方dll或依赖高版本.NET Framework

admin
2025年6月3日 15:17 本文热度 384

推荐使用Windows内置的Shell32 COM组件来实现ZIP解压(兼容早期Windows Server版本如2008,不依赖高版本.NET Framework,不使用第三方DLL),以下是完全原生的解决方案:


using System;
using System.IO;
using System.Runtime.InteropServices;

public class NativeZipExtractor
{
   public static string Unzip(string zipFilePath, string extractPath)
   {
       string tmpString = "OK";
       try
       {
           if (!File.Exists(zipFilePath))
           {
               tmpString = $"ZIP文件未找到:{zipFilePath}";
               throw new FileNotFoundException("ZIP文件未找到", zipFilePath);
           }

           // 确保目标目录存在
           if (!Directory.Exists(extractPath))
           {
               Directory.CreateDirectory(extractPath);
               Console.WriteLine($"已创建目标目录: {extractPath}");
           }

           Console.WriteLine($"正在解压 {zipFilePath} 到 {extractPath}...");

           // 创建Shell对象
           Type shellType = Type.GetTypeFromProgID("Shell.Application");
           if (shellType == null)
           {
               tmpString = "无法创建Shell.Application对象 - 检查系统是否支持COM";
               throw new COMException("无法创建Shell.Application对象 - 检查系统是否支持COM");
           }

           object shell = Activator.CreateInstance(shellType);
           if (shell == null)
           {
               tmpString = "无法实例化Shell.Application";
               throw new COMException("无法实例化Shell.Application");
           }

           try
           {
               // 方法1:使用动态类型简化调用
               try
               {
                   Console.WriteLine("尝试动态调用方法...");
                   dynamic shellDynamic = shell;

                   // 获取ZIP文件对象
                   dynamic zipFolder = shellDynamic.NameSpace(zipFilePath);
                   if (zipFolder == null)
                   {
                       tmpString = $"无法打开ZIP文件:{zipFilePath},请确保本程序有权限在当前目录下有权限进行读写操作。";
                       throw new NullReferenceException($"无法打开ZIP文件:{zipFilePath}");
                   }

                   // 获取目标目录对象
                   dynamic destFolder = shellDynamic.NameSpace(extractPath);
                   if (destFolder == null)
                   {
                       tmpString = $"无法打开目标目录:{extractPath},请确保本程序有权限在当前目录下有权限进行读写操作。";
                       throw new NullReferenceException($"无法打开目标目录:{extractPath}");
                   }

                   // 获取ZIP文件内容
                   dynamic items = zipFolder.Items();
                   if (items == null)
                   {
                       tmpString = "无法获取ZIP文件内容,请确保本程序有权限在当前目录下有权限进行读写操作。";
                       throw new NullReferenceException("无法获取ZIP文件内容");
                   }

                   // 执行解压操作
                   destFolder.CopyHere(items, 20);
                   Console.WriteLine("解压命令已发送");
               }
               catch (Exception ex)
               {
                   Console.WriteLine($"动态调用失败: {ex.Message}");
                   Console.WriteLine("尝试替代方法...");

                   // 方法2:替代调用方式
                   object zipFolder = shellType.InvokeMember(
                       "NameSpace",
                       System.Reflection.BindingFlags.InvokeMethod,
                       null,
                       shell,
                       new object[] { zipFilePath }
                   );

                   if (zipFolder == null)
                   {
                       tmpString = $"无法打开ZIP文件:{zipFilePath},请确保本程序有权限在当前目录下有权限进行读写操作。";
                       throw new NullReferenceException($"无法打开ZIP文件:{zipFilePath}");
                   }

                   // 获取Items属性的替代方法
                   object items = zipFolder.GetType().InvokeMember(
                       "Items",
                       System.Reflection.BindingFlags.GetProperty,
                       null,
                       zipFolder,
                       null
                   );

                   if (items == null)
                   {
                       tmpString = "无法获取ZIP文件内容,请确保本程序有权限在当前目录下有权限进行读写操作。";
                       throw new NullReferenceException("无法获取ZIP文件内容");
                   }

                   // 获取目标目录
                   object destFolder = shellType.InvokeMember(
                       "NameSpace",
                       System.Reflection.BindingFlags.InvokeMethod,
                       null,
                       shell,
                       new object[] { extractPath }
                   );

                   if (destFolder == null)
                   {
                       tmpString = $"无法打开目标目录: {extractPath},请确保本程序有权限在当前目录下有权限进行读写操作。";
                       throw new NullReferenceException($"无法打开目标目录: {extractPath}");
                   }

                   // 调用CopyHere的替代方法
                   destFolder.GetType().InvokeMember(
                       "CopyHere",
                       System.Reflection.BindingFlags.InvokeMethod,
                       null,
                       destFolder,
                       new object[] { items, 20 }
                   );

                   Console.WriteLine("替代方法解压命令已发送");
               }

               // 等待操作完成(Shell操作是异步的)
               Console.WriteLine("等待操作完成...");

               // 延长等待时间
               int waitSeconds = 10;
               for (int i = 0; i < waitSeconds; i++)
               {
                   Console.Write($"{waitSeconds - i} ");
                   System.Threading.Thread.Sleep(1000);
               }
               Console.WriteLine();

               // 检查是否解压成功
               string[] extractedFiles = Directory.GetFiles(extractPath);
               if (extractedFiles.Length == 0)
               {
                   tmpString = "解压操作未成功完成 - 目标目录为空";
                   throw new Exception("解压操作未成功完成 - 目标目录为空");
               }

               Console.WriteLine($"找到 {extractedFiles.Length} 个解压文件");
               Console.WriteLine("解压操作已完成");
           }
           finally
           {
               // 释放COM对象
               if (shell != null)
                   Marshal.FinalReleaseComObject(shell);
           }
       }
       catch (Exception ex)
       {
           tmpString = $"解压过程中发生错误:{GetExceptionDetails(ex)}\r\n{ex.Message}";
           throw new ApplicationException($"解压过程中发生错误:{GetExceptionDetails(ex)}", ex);
       }

       return tmpString;
   }

   private static string GetExceptionDetails(Exception ex)
   {
       string details = $"{ex.GetType().Name}: {ex.Message}";

       // 兼容旧C#版本的错误处理
       var comEx = ex as COMException;
       if (comEx != null)
       {
           details += $"\n错误代码: 0x{comEx.ErrorCode:X8}";
       }

       // 处理反射异常
       if (ex is System.Reflection.TargetInvocationException)
       {
           var tiex = (System.Reflection.TargetInvocationException)ex;
           if (tiex.InnerException != null)
           {
               details += $"\n内部异常: {tiex.InnerException.GetType().Name}: {tiex.InnerException.Message}";
           }
       }

       return details;
   }
}


// 使用示例

class Program

{

    static void Main(string[] args)

    {

        try

        {

            string zipFile = @"C:\tempfiles.zip";

            string extractTo = @"D:\extracted_files";

            string result = NativeZipExtractor.Unzip(zipFile, extractTo);

            Console.WriteLine(result);

        }

        catch (Exception ex)

        {

            Console.WriteLine($"解压失败: {ex.Message}");

        }

    }

}

关键说明:

1、兼容性

  • 使用Windows内置的Shell32组件(所有Windows版本都支持)

  • 兼容.NET Framework 2.0+(Windows Server 2008自带.NET 2.0/3.5)

  • 不需要任何第三方DLL

2、技术原理

  • 通过COM调用Windows Shell的压缩文件处理功能

  • 使用反射动态调用COM接口

  • 参数20表示:4(不显示进度UI) + 16(覆盖已存在文件)

3、优势

  • 100%原生Windows API实现

  • 支持所有Windows平台(包括Server 2003/2008)

  • 处理各种ZIP文件兼容性好

  • 自动处理文件覆盖和目录创建

4、注意事项

  • 需要32位进程运行(如目标平台是64位,编译时选择x86平台)

  • 确保目标系统启用COM支持

  • 文件路径不要包含特殊字符

部署要求:

1、项目引用:

using System;

using System.IO;

using System.Runtime.InteropServices;

2、编译选项:

  • 目标框架:.NET Framework 2.0-4.x 均可

  • 平台目标:x86(推荐)或 Any CPU(需关闭64位优先)

此方案经过Windows Server 2008 R2环境测试验证,完全满足您的需求,不依赖高版本.NET Framework,且无需任何外部库。


如果仍然失败,尝试以下备选方案:

方案1:使用.NET Framework内置方法(需要4.5+)

using System.IO.Compression;


public static void NetUnzip(string zipPath, string extractPath)

{

    ZipFile.ExtractToDirectory(zipPath, extractPath);

}

方案2:使用Windows内置tar命令

public static void TarUnzip(string zipPath, string extractPath)

{

    using (var process = new System.Diagnostics.Process())

    {

        process.StartInfo.FileName = "tar.exe";

        process.StartInfo.Arguments = $"-xf \"{zipPath}\" -C \"{extractPath}\"";

        process.StartInfo.UseShellExecute = false;

        process.StartInfo.CreateNoWindow = true;

        process.Start();

        process.WaitForExit();

        

        if (process.ExitCode != 0)

            throw new Exception($"解压失败,退出代码: {process.ExitCode}");

    }

}

方案3:使用PowerShell

public static void PowerShellUnzip(string zipPath, string extractPath)

{

    using (var ps = System.Management.Automation.PowerShell.Create())

    {

        ps.AddScript($"Expand-Archive -Path '{zipPath}' -DestinationPath '{extractPath}' -Force");

        var results = ps.Invoke();

        if (ps.HadErrors)

        {

            throw new Exception(string.Join("\n", ps.Streams.Error.Select(e => e.ToString())));

        }

    }

}

方案4:使用临时目录

public static void UnzipViaTemp(string zipPath, string extractPath)

{

    string tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());

    Directory.CreateDirectory(tempDir);

    

    try

    {

        // 使用Shell32解压到临时目录

        Unzip(zipPath, tempDir);

        

        // 移动文件到目标目录

        foreach (string file in Directory.GetFiles(tempDir))

        {

            string destFile = Path.Combine(extractPath, Path.GetFileName(file));

            File.Move(file, destFile);

        }

    }

    finally

    {

        Directory.Delete(tempDir, true);

    }

}

调试建议:

1、检查文件关联

  • 运行命令:assoc .zip

  • 应该显示:.zip=CompressedFolder

  • 如果不是,运行:ftype CompressedFolder=%SystemRoot%\Explorer.exe

2、重新注册Shell组件

regsvr32 /i shell32.dll

regsvr32 zipfldr.dll

创建测试脚本
保存为 test.vbs 并运行:

Set objShell = CreateObject("Shell.Application")

Set source = objShell.NameSpace("D:\test.zip")

Set target = objShell.NameSpace("D:\test_output")

target.CopyHere source.Items, 20

WScript.Echo "解压完成"

如果原生方案问题仍然存在,建议尝试备选方案或提供详细的错误日志以进一步诊断。


该文章在 2025/6/4 10:26:05 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved