System.Diagnostics.Process 是 .NET 啟動、控制、監控作業系統進程的核心 API。無論是呼叫 CLI 工具、轉檔程式、瀏覽器,還是啟動另一個 .NET 應用程式,掌握 Process 與 ProcessStartInfo 的關鍵屬性,就能處理「隱藏黑框、傳遞參數、捕獲輸出、同步/非同步等待」等實務需求。
using System.Diagnostics;
Process.Start("notepad.exe"); // 系統路徑下的 exe 可直接用檔名
Process.Start(@"C:\Tools\MyTool.exe", "arg1 arg2"); // 帶參數
此為 Fire-and-Forget,呼叫端不等待子進程結束。
var p = Process.Start("notepad.exe");
p.WaitForExit(); // 封鎖當前執行緒,直到記事本關閉
Console.WriteLine($"Exit code: {p.ExitCode}");
var psi = new ProcessStartInfo
{
FileName = @"C:\Tools\ffmpeg.exe", // 完整路徑或 PATH 內指令
Arguments = "-i input.mp4 -vn output.mp3", // 命令列參數
UseShellExecute = false, // 關鍵:false 才能重導向 IO、隱藏視窗
CreateNoWindow = true, // 不建立視窗(無黑框閃爍)
RedirectStandardOutput = true, // 捕獲標準輸出
RedirectStandardError = true, // 捕獲錯誤輸出
RedirectStandardInput = true, // 向子進程寫入輸入
WorkingDirectory = @"C:\Work", // 工作目錄
Verb = "runas" // 需管理員權限(UAC 提升)
};
using (var proc = Process.Start(psi))
{
// 非同步讀取輸出避免死鎖
string output = await proc.StandardOutput.ReadToEndAsync();
string error = await proc.StandardError.ReadToEndAsync();
await proc.WaitForExitAsync(); // .NET 6+ 非同步等待
Console.WriteLine($"ExitCode: {proc.ExitCode}");
Console.WriteLine(output);
}
| 屬性 | 用途 | 備註 |
|---|---|---|
FileName | 可執行檔路徑或指令 | 若 UseShellExecute=true 可為網址、文件關聯 |
Arguments | 命令列參數字串 | 含空白路徑請用雙引號包裹 |
UseShellExecute | 是否用 Shell 執行 | false 才能重導向 IO、隱藏視窗、設定 Verb |
CreateNoWindow | 不建立主控台視窗 | 僅 UseShellExecute=false 生效 |
RedirectStandardOutput/Error/Input | 重導向標準串流 | 需 UseShellExecute=false |
WorkingDirectory | 子進程工作目錄 | 相對路徑解析基準 |
Verb | 動詞 | runas 觸發 UAC,open 等 |
StandardOutputEncoding | 輸出編碼 | .NET 6+,解決中文亂碼 |
var psi = new ProcessStartInfo("dotnet", "build --verbosity quiet")
{
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
using (var p = Process.Start(psi))
{
p.OutputDataReceived += (s, e) => { if (e.Data != null) Console.WriteLine($"[OUT] {e.Data}"); };
p.ErrorDataReceived += (s, e) => { if (e.Data != null) Console.Error.WriteLine($"[ERR] {e.Data}"); };
p.BeginOutputReadLine();
p.BeginErrorReadLine();
await p.WaitForExitAsync();
}
if (!IsRunAsAdmin())
{
var psi = new ProcessStartInfo(Process.GetCurrentProcess().MainModule.FileName)
{
UseShellExecute = true,
Verb = "runas"
};
Process.Start(psi);
Environment.Exit(0);
}
bool IsRunAsAdmin()
{
using var id = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(id);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
// .NET Core 3.0+ 跨平台開啟 URL 或檔案
Process.Start(new ProcessStartInfo("https://example.com") { UseShellExecute = true });
Process.Start(new ProcessStartInfo(@"README.md") { UseShellExecute = true });
ReadToEnd() 可能填滿管道緩衝區 → 改用事件式 OutputDataReceived 或非同步 ReadToEndAsync()。StandardOutputEncoding = Encoding.UTF8(.NET 6+)或 proc.StandardOutput.CurrentEncoding = Encoding.GetEncoding(950)(繁中環境)。Arguments = "\"C:\\Program Files\\Tool.exe\" arg1\"。Process 實作 IDisposable,務必 using 或手動釋放,否則句柄洩漏。false;要開啟網址/文件關聯/提權 → true。WaitForExitAsync(CancellationToken):可取消的非同步等待。Process.StartAsync(ProcessStartInfo, CancellationToken):非同步啟動。Process.GetProcessesByName、Process.GetCurrentProcess() 等查詢 API 維持不變。熟練運用 ProcessStartInfo 的三大核心組合——UseShellExecute=false + CreateNoWindow=true + RedirectStandardOutput=true——即能優雅地在後台執行任何命令列工具,並完整掌控其生命週期與輸出。