首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 啟動本機外部程式完整指南:Process.Start 進階用法與常見陷阱

     編輯:關於C#

基礎用法


using System.Diagnostics;

// 最簡單
Process.Start("notepad.exe");
Process.Start("calc.exe");

// 開啟檔案/網址 (關聯預設程式)
Process.Start("https://example.com");
Process.Start(@"C:\Docs\report.pdf");
Process.Start(@"D:\Projects\MyApp.sln");

進階控制:ProcessStartInfo


var psi = new ProcessStartInfo
{
    FileName = "notepad.exe",
    Arguments = @"C:\Temp\readme.txt", // 傳遞參數
    WorkingDirectory = @"C:\Temp",     // 工作目錄
    Verb = "runas",                    // 以管理員身分執行 (需 UAC 提權)
    WindowStyle = ProcessWindowStyle.Maximized, // 視窗狀態
    UseShellExecute = true,            // true: Shell 執行 (支援 Verb/關聯), false: 直接建立進程
    CreateNoWindow = false,            // 不建立視窗 (僅 UseShellExecute=false 時有效)
    RedirectStandardInput = false,     // 重導向標準輸入/輸出/錯誤
    RedirectStandardOutput = false,
    RedirectStandardError = false,
    StandardOutputEncoding = Encoding.UTF8,
    StandardErrorEncoding = Encoding.UTF8
};
Process.Start(psi);

關鍵屬性決策表

需求UseShellExecuteRedirectStandardOutputCreateNoWindow備註
啟動 GUI 應用程式 (記事本、瀏覽器)truefalsefalse預設行為
啟動 CLI 工具並捕獲輸出falsetruetrue必須搭配 UseShellExecute=false
以管理員身分執行truefalsefalseVerb="runas" 觸發 UAC
隱藏主控台視窗 (背景服務)falsetrue/falsetrue無視窗閃爍
開啟網址/文件關聯truefalsefalseFileName 為 URL/路徑

捕獲輸出完整範例


public static (int ExitCode, string Output, string Error) RunCli(string fileName, string args, int timeoutMs = 30000)
{
    var psi = new ProcessStartInfo
    {
        FileName = fileName,
        Arguments = args,
        UseShellExecute = false,
        RedirectStandardOutput = true,
        RedirectStandardError = true,
        CreateNoWindow = true,
        StandardOutputEncoding = Encoding.UTF8,
        StandardErrorEncoding = Encoding.UTF8
    };

    using (var proc = Process.Start(psi))
    {
        string output = proc.StandardOutput.ReadToEnd();
        string error = proc.StandardError.ReadToEnd();
        bool exited = proc.WaitForExit(timeoutMs);
        if (!exited) proc.Kill();
        return (proc.ExitCode, output, error);
    }
}

// 使用
var (code, out, err) = RunCli("dotnet", "--version");
Console.WriteLine($"Exit: {code}, Out: {out.Trim()}");

非同步事件式讀取 (避免死結)


public static async Task<(int ExitCode, string Output, string Error)> RunCliAsync(string fileName, string args)
{
    var tcs = new TaskCompletionSource<(int, string, string)>();
    var psi = new ProcessStartInfo
    {
        FileName = fileName,
        Arguments = args,
        UseShellExecute = false,
        RedirectStandardOutput = true,
        RedirectStandardError = true,
        CreateNoWindow = true
    };

    using (var proc = new Process { StartInfo = psi, EnableRaisingEvents = true })
    {
        var outBuf = new StringBuilder();
        var errBuf = new StringBuilder();

        proc.OutputDataReceived += (s, e) => { if (e.Data != null) outBuf.AppendLine(e.Data); };
        proc.ErrorDataReceived += (s, e) => { if (e.Data != null) errBuf.AppendLine(e.Data); };

        proc.Exited += (s, e) => tcs.TrySetResult((proc.ExitCode, outBuf.ToString(), errBuf.ToString()));

        proc.Start();
        proc.BeginOutputReadLine();
        proc.BeginErrorReadLine();

        return await tcs.Task;
    }
}

常見陷阱與解決

總結

`Process.Start` 看似簡單,實則藏著 **Shell vs 直接建立、重導向管道死結、UAC 提權、編碼、視窗風格** 等關鍵決策。掌握 `ProcessStartInfo` 完整屬性矩陣,依需求選擇正確組合,並善用非同步事件式讀取避免死結,即能穩健啟動並控制任何外部程式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
問題原因解決
死結同步 `ReadToEnd` + 大量輸出填滿管道緩衝區非同步事件讀取 / 交錯讀取雙管道 / 增加緩衝區
Verb="runas" 不生效UseShellExecute=false必須 UseShellExecute=true
檔案關聯不生效UseShellExecute=falsetrue 或明確指定關聯程式路徑
中文參數亂碼編碼不匹配StandardOutputEncoding = Encoding.UTF8 / 系統預設編碼
等待逾時未結束子程式卡住/等待輸入設定 Timeout + Kill / 標準輸入寫入結束訊號