LHA (LZH) 是日本早期流行的壓縮格式,.NET Framework 內建不支援。常見做法是 P/Invoke 呼叫開源的 `unlha32.dll` (C 語言實作)。本文提供完整的 C# 靜態類別封裝,含版本檢查、執行狀態檢查、檔案驗證、解壓縮與錯誤代碼對照。
using System;
using System.IO;
using System.Runtime.InteropServices;
public static class LhaExtractor
{
// --- 1. DLL 匯入宣告 ---
[DllImport("unlha32.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern ushort UnlhaGetVersion();
[DllImport("unlha32.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnlhaGetRunning();
[DllImport("unlha32.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnlhaCheckArchive(string szFileName, int iMode);
[DllImport("unlha32.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int Unlha(int hwnd, string szCmdLine, string szOutput, int dwSize);
// --- 2. 錯誤代碼對照 ---
private enum UnlhaErrorCode
{
Success = 0,
Cancelled = 32800, // 使用者取消
// 其他代碼參考 DLL 文件
}
// --- 3. 公開解壓方法 ---
///
/// 解壓 LHA 檔案
///
/// .lha 檔案完整路徑
/// 解壓目標目錄 (null/empty 同檔案名建立子目錄)
/// 解壓成功後是否刪除原壓縮檔
/// 成功 true / 失敗拋出例外
public static bool Extract(string archivePath, string extractDir = null, bool deleteArchive = false)
{
if (!File.Exists(archivePath))
throw new FileNotFoundException("找不到壓縮檔", archivePath);
// 1. 檢查 DLL 是否存在
try { var _ = UnlhaGetVersion(); }
catch (DllNotFoundException)
{ throw new DllNotFoundException("unlha32.dll 不在 PATH 或應用程式目錄中"); }
// 2. 檢查 DLL 是否忙碌
if (UnlhaGetRunning())
throw new InvalidOperationException("DLL 正在執行其他解壓作業,請稍後再試");
// 3. 檢查檔案有效性
if (!UnlhaCheckArchive(archivePath, 0))
throw new InvalidDataException("檔案損壞或非有效 LHA 格式");
// 4. 決定解壓路徑
string targetDir = string.IsNullOrEmpty(extractDir)
? Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
Path.GetFileNameWithoutExtension(archivePath))
: extractDir;
if (!Directory.Exists(targetDir)) Directory.CreateDirectory(targetDir);
// 5. 呼叫解壓 (命令列參數: x "來源" "目標")
string cmd = $"x \"{archivePath}\" \"{targetDir}\"";
int ret = Unlha(0, cmd, null, 0);
// 6. 結果判斷
if (ret != (int)UnlhaErrorCode.Success)
{
string msg = ret == (int)UnlhaErrorCode.Cancelled
? "使用者取消解壓"
: $"解壓失敗,錯誤代碼: {ret}";
throw new Exception(msg);
}
// 7. 選擇性刪除原檔
if (deleteArchive) File.Delete(archivePath);
return true;
}
}
try
{
bool ok = LhaExtractor.Extract(@"C:\Data\archive.lha", @"C:\Output\", deleteArchive: true);
Console.WriteLine("解壓完成");
}
catch (Exception ex)
{
Console.WriteLine($"錯誤: {ex.Message}");
}
var archive = ArchiveFactory.Open(stream); archive.WriteToDirectory(dir);P/Invoke 呼叫 `unlha32.dll` 是解決舊系統 LHA 相容性的快速方案,但部署麻煩、平台受限。新專案**強烈建議改用 SharpCompress 等純 Managed 函式庫**,一次解決所有壓縮格式支援問題。