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

C# 啟動與關閉外部程式進程:Process 類別 vs Win32 API 完整比較

     編輯:關於C語言

兩種啟動方式

方式一:.NET 原生 Process.Start (推薦)

using System.Diagnostics;

int processId;

private void BtnStart_Click(object sender, EventArgs e)
{
    var proc = Process.Start(@"\\NandFlash\SerialTST.exe", "");
    processId = proc.Id; // 取得 PID 供後續關閉
}
  • 程式碼簡潔、跨平台 (Windows/Linux/macOS .NET Core)。
  • 自動處理路徑含空白、參數逸出等細節。
  • 回傳 Process 物件,可直接 WaitForExit()、讀取 StandardOutput 等。

方式二:P/Invoke CreateProcess (僅限極特殊需求)

using System.Runtime.InteropServices;

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool CreateProcess(
    string lpApplicationName,
    string lpCommandLine,
    IntPtr lpProcessAttributes,
    IntPtr lpThreadAttributes,
    bool bInheritHandles,
    uint dwCreationFlags,
    IntPtr lpEnvironment,
    string lpCurrentDirectory,
    [In] ref STARTUPINFO lpStartupInfo,
    out PROCESS_INFORMATION lpProcessInformation);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct STARTUPINFO
{
    public int cb;
    public string lpReserved;
    public string lpDesktop;
    public string lpTitle;
    public int dwX, dwY, dwXSize, dwYSize;
    public int dwXCountChars, dwYCountChars;
    public int dwFillAttribute;
    public int dwFlags;
    public short wShowWindow;
    public short cbReserved2;
    public IntPtr lpReserved2;
    public IntPtr hStdInput, hStdOutput, hStdError;
}

[StructLayout(LayoutKind.Sequential)]
struct PROCESS_INFORMATION
{
    public IntPtr hProcess;
    public IntPtr hThread;
    public int dwProcessId;
    public int dwThreadId;
}

private void BtnStartApi_Click(object sender, EventArgs e)
{
    var si = new STARTUPINFO { cb = Marshal.SizeOf(typeof(STARTUPINFO)) };
    CreateProcess(@"\\NandFlash\SerialTST.exe", "", IntPtr.Zero, IntPtr.Zero,
        false, 0, IntPtr.Zero, null, ref si, out var pi);
    processId = pi.dwProcessId;
}
  • 需定義複雜結構體、處理 Unicode/ANSI、錯誤碼檢查 (Marshal.GetLastWin32Error())。
  • 唯一優勢:極度底層控制 (如指定父進程、Token、Desktop、Console 模式等)。
  • 一般應用勿使用,維護成本極高。

關閉進程:統一使用 Process.GetProcessById

private void BtnStop_Click(object sender, EventArgs e)
{
    try
    {
        var proc = Process.GetProcessById(processId);
        proc.Kill(); // 強制終止
        // 或 proc.CloseMainWindow() 禮貌關閉 GUI 程式
    }
    catch (ArgumentException)
    {
        // 進程已不存在
    }
}

進階情境

需求做法
等待結束並取得 ExitCodeproc.WaitForExit(); int code = proc.ExitCode;
捕捉標準輸出/錯誤proc.StartInfo.RedirectStandardOutput = true; 並讀取 proc.StandardOutput.ReadToEnd()
以不同使用者身分執行ProcessStartInfo.Verb = "runas" (UAC) 或設定 UserName/Password/Domain
隱藏視窗proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
非同步啟動await Task.Run(() => Process.Start(...))

最佳實踐清單

  1. 優先 Process.Start,僅在需要 CreateProcess 獨有參數 (如 CREATE_BREAKAWAY_FROM_JOB) 時才 P/Invoke。
  2. 啟動後立即儲存 Id,避免同名進程混淆。
  3. 關閉時優先 CloseMainWindow(),失敗再 Kill()。
  4. using 或 try/finally 確保 Process 物件釋放 (非 Unmanaged 資源,但屬良好習慣)。
  5. 記錄啟動/結束日誌,便於排查殭屍進程。

結語

.NET Process 類別已封裝絕大多數啟動/管理外部進程的需求,除非遇到極罕見的底層需求,否則無需自行 P/Invoke Win32 API。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved