System.Diagnostics.Process 類別提供啟動、控制、監控作業系統進程的功能。透過啟動 cmd.exe 並傳遞參數,即可在 C# 中執行任意命令列指令並捕獲輸出。
| 屬性 | 用途 | 典型值 |
|---|---|---|
| FileName | 要啟動的執行檔 | "cmd.exe" |
| Arguments | 命令列參數 | "/c dir"(執行完畢關閉視窗) |
| UseShellExecute | 是否使用 Shell 執行 | false(必須為 false 才能重導向 I/O) |
| RedirectStandardInput | 重導向標準輸入 | true |
| RedirectStandardOutput | 重導向標準輸出 | true |
| RedirectStandardError | 重導向標準錯誤 | true |
| CreateNoWindow | 不建立視窗 | true(背景執行) |
using System.Diagnostics;
public static string RunCommand(string command, int timeoutMs = 30000)
{
var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/c {command}",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
StandardOutputEncoding = System.Text.Encoding.UTF8, // 避免中文亂碼
StandardErrorEncoding = System.Text.Encoding.UTF8
};
using (var process = Process.Start(startInfo))
{
if (process == null) throw new InvalidOperationException("無法啟動進程");
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
bool exited = process.WaitForExit(timeoutMs);
if (!exited)
{
process.Kill();
throw new TimeoutException($"命令執行超時 ({timeoutMs} ms)");
}
if (process.ExitCode != 0 && !string.IsNullOrEmpty(error))
throw new InvalidOperationException($"命令失敗 (ExitCode={process.ExitCode}): {error}");
return output.Trim();
}
}
Arguments = "/k"; // 執行後保持視窗,適合除錯
// 透過 StandardInput.WriteLine() 送入多行指令
process.StandardInput.WriteLine("cd C:\\Projects");
process.StandardInput.WriteLine("dotnet build");
process.StandardInput.WriteLine("exit"); // 必須送入 exit 結束
process.OutputDataReceived += (s, e) => { if (e.Data != null) Console.WriteLine(e.Data); };
process.ErrorDataReceived += (s, e) => { if (e.Data != null) Console.Error.WriteLine(e.Data); };
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
startInfo.Verb = "runas"; // 需 UAC 提權
StandardOutputEncoding / StandardErrorEncoding 為 Encoding.UTF8 或 Encoding.GetEncoding(950)(繁體中文預設代碼頁)。ReadToEnd() 時若輸出超過緩衝區會卡住,大量輸出請用非同步事件式讀取。Arguments = $\"/c \\\"{path}\\\" {args}\"。