Web 應用若需在伺服器端對上傳檔案進行壓縮或解壓縮,可透過 `System.Diagnostics.Process` 啟動已安裝的 WinRAR 執行檔。本文提供完整實作:從登錄表自動偵測 `WinRAR.exe` 路徑、建構命令列參數、設定隱藏視窗與工作目錄、非同步執行與錯誤處理。
1. 讀取登錄表 HKEY_CLASSES_ROOT\Applications\WinRAR.exe\Shell\Open\Command → 取得完整命令字串 (含參數佔位符 "%1") 2. 解析出 WinRAR.exe 實際路徑 3. 建構參數: 壓縮: a -r -ep1 "目標.rar" "來源路徑\*" 解壓縮: x -o+ "來源.rar" "目標資料夾\" 4. ProcessStartInfo 設定: FileName = WinRAR路徑 Arguments = 參數字串 WindowStyle = Hidden WorkingDirectory = 作業目錄 UseShellExecute = false (必要時) RedirectStandardOutput/Error = true (需捕獲輸出時) 5. Process.Start() 執行 6. 等待結束 / 非同步監控 / 處理 ExitCode
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html>
<html xmlns="https://www.w3.org/1999/xhtml">
<head runat="server">
<title>伺服器端 RAR 壓縮/解壓縮示範</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="btnCompress" runat="server" Text="壓縮 C:\Data\ → C:\Output\data.rar"
OnClick="btnCompress_Click" />
<asp:Button ID="btnExtract" runat="server" Text="解壓縮 C:\Output\data.rar → C:\Extract\"
OnClick="btnExtract_Click" />
<br /><br />
<asp:Label ID="lblResult" runat="server" ForeColor="Green" />
</div>
</form>
</body>
</html>
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.Win32;
using System.Web.UI;
public partial class _Default : Page
{
protected void btnCompress_Click(object sender, EventArgs e)
{
ExecuteRar("a", @"C:\Output\data.rar", @"C:\Data\", "壓縮");
}
protected void btnExtract_Click(object sender, EventArgs e)
{
ExecuteRar("x", @"C:\Output\data.rar", @"C:\Extract\", "解壓縮");
}
private void ExecuteRar(string command, string archivePath, string targetPath, string actionName)
{
try
{
// 1. 從登錄表取得 WinRAR.exe 路徑
string rarPath = GetWinRarPath();
if (string.IsNullOrEmpty(rarPath) || !File.Exists(rarPath))
{
lblResult.Text = $"❌ 找不到 WinRAR.exe,請確認已安裝。路徑: {rarPath}";
return;
}
// 2. 建構參數
string arguments = BuildArguments(command, archivePath, targetPath);
// 3. 設定 Process
var psi = new ProcessStartInfo
{
FileName = rarPath,
Arguments = arguments,
WindowStyle = ProcessWindowStyle.Hidden,
WorkingDirectory = Path.GetDirectoryName(archivePath) ?? @"C:\",
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
// 4. 執行
using (var proc = Process.Start(psi))
{
string output = proc.StandardOutput.ReadToEnd();
string error = proc.StandardError.ReadToEnd();
proc.WaitForExit(60000); // 60 秒逾時
if (proc.ExitCode == 0)
{
lblResult.Text = $"✅ {actionName} 成功!ExitCode: 0";
}
else
{
lblResult.Text = $"❌ {actionName} 失敗,ExitCode: {proc.ExitCode}
Error: {error}
Output: {output}";
}
}
}
catch (Exception ex)
{
lblResult.Text = $"❌ 例外: {ex.Message}";
}
}
private string GetWinRarPath()
{
// 嘗試多個登錄表位置 (32/64 位元、不同版本)
string[] regPaths =
{
@"Applications\WinRAR.exe\Shell\Open\Command",
@"WinRAR\Shell\Open\Command",
@"Applications\WinRAR32.exe\Shell\Open\Command"
};
foreach (var regPath in regPaths)
{
using (var key = Registry.ClassesRoot.OpenSubKey(regPath))
{
if (key != null)
{
string cmd = key.GetValue("")?.ToString();
if (!string.IsNullOrEmpty(cmd))
{
// 解析命令字串:"C:\Program Files\WinRAR\WinRAR.exe" "%1"
var match = System.Text.RegularExpressions.Regex.Match(cmd, @"""(.*?)""");
if (match.Success && File.Exists(match.Groups[1].Value))
return match.Groups[1].Value;
}
}
}
}
return null;
}
private string BuildArguments(string command, string archivePath, string targetPath)
{
// 參考 WinRAR 命令列語法
switch (command.ToLower())
{
case "a": // 壓縮
// a -r -ep1 -ibck "archive.rar" "source\*"
return $"-r -ep1 -ibck \"{archivePath}\" \"{targetPath}\\*\"";
case "x": // 解壓縮 (保留路徑)
// x -o+ -ibck "archive.rar" "dest\"
return $"-o+ -ibck \"{archivePath}\" \"{targetPath}\\\"";
case "e": // 解壓縮 (不保留路徑)
return $"-o+ -ibck \"{archivePath}\" \"{targetPath}\\\"";
default:
throw new ArgumentException("不支援的命令: " + command);
}
}
}
| 參數 | 說明 |
|---|---|
| `a` | 加入檔案到壓縮檔 (建立/更新) |
| `x` | 解壓縮並保留完整路徑結構 |
| `e` | 解壓縮但忽略路徑 (所有檔案平鋪到目標資料夾) |
| `-r` | 遞迴子目錄 |
| `-ep1` | 排除基礎目錄名稱 (避免壓縮包含完整絕對路徑) |
| `-o+` | 覆蓋既有檔案不提示 |
| `-ibck` | 背景模式 (無視窗、無進度條) |
| `-hp[pwd]` | 設定密碼加密 (慎用,命令列可見) |
| `-v | 分卷壓縮 (如 `-v100m`) |
| `-rr[N]` | 加入修復記錄 |
| 庫 | NuGet | 支援格式 | 特色 |
|---|---|---|---|
| SharpCompress | SharpCompress | RAR, ZIP, 7Z, TAR, GZIP, BZIP2 | 純 managed、支援 RAR5、非同步、串流 |
| System.IO.Compression.ZipArchive | 內建 (.NET Core/5+) | ZIP | 零依賴、高效能、標準 API |
| SevenZipSharp | SevenZipSharp | 7Z, ZIP, RAR, ISO, CAB... | 7-ZIP 封裝、需 7z.dll |
| ICSharpCode.SharpZipLib | SharpZipLib | ZIP, GZIP, BZIP2, TAR | 經典、成熟、支援 .NET Framework |
// SharpCompress 範例:解壓縮 RAR (純 .NET、無外部相依)
using SharpCompress.Archives.Rar;
using SharpCompress.Common;
using (var archive = RarArchive.Open(archivePath))
{
foreach (var entry in archive.Entries.Where(e => !e.IsDirectory))
{
entry.WriteToDirectory(targetPath, new ExtractionOptions
{
ExtractFullPath = true,
Overwrite = true
});
}
}
雖然呼叫 WinRAR 是快速整合現有壓縮流程的捷徑,但**安全風險、部署相依性、授權成本、跨平台限制**使其不適合現代雲原生應用。採用 **SharpCompress** 等純 .NET 庫,享受零部署、跨平台、可審計原始碼、無授權疑慮的優勢,才是長遠之計。