91网首页-91网页版-91网在线观看-91网站免费观看-91网站永久视频-91网站在线播放

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

C#原生代碼將zip壓縮文件解壓到指定目錄,不需要借助第三方dll或依賴高版本.NET Framework

admin
2025年6月3日 15:17 本文熱度 403

推薦使用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

主站蜘蛛池模板: 欧美综合国产 | 91国内在线视 | 午夜日韩在线观看 | 无码成人| 九九国产热播 | 国产福利影院在线 | 91免费国| 黑人狂躁日 | 精品一区二区五 | 中文字幕日韩一区 | 国产精品亚洲玖玖 | 国产在线91下载 | 乱伦精品综合 | 国产在线拍偷自揄 | 最新国产在线拍揄自揄视频 | 日韩中文字幕a | 日韩精品综 | 国产高清久 | 日韩欧美亚洲午夜 | 日本亚洲精品成人 | 国产精品一品道 | 国产片第一福利片 | 日韩第一页在线观看 | 国产高清精品一区 | 日本欧美一 | 欧美一区日韩二区 | 人人艹97| 成人亚洲欧美综合 | 91精品在线播放 | 中文字幕v| 日本免费一二 | 欧美亚洲日本日韩 | 国产AⅤ精品 | 日韩中文字幕无砖 | 国产盗拍精品视频 | 精品日韩第56页 | 国产精品视频二区在 | 日韩免费视频网址 | 99热99然后 | 日韩亚洲一区在线 | 天美麻花果冻 |