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

C# 進程管理與強制終止:System.Diagnostics.Process 完整應用指南

     編輯:關於C語言

前言

.NET 透過 `System.Diagnostics.Process` 提供強大的進程列舉、資訊查詢、啟動與終止功能。本文詳細說明如何掃描系統進程、讀取模組路徑、版本資訊,並安全地終止指定進程,附帶完整 WinForms 範例代碼。

核心 API 概覽

成員用途
Process.GetProcesses()取得所有進程陣列(含系統進程)
Process.GetProcessesByName(name)依名稱篩選(不含 .exe)
Process.Start(startInfo)啟動新進程
process.Kill()強制終止(不給儲存機會)
process.CloseMainWindow()優雅關閉(發送 WM_CLOSE,僅限有視窗進程)
process.Modules載入模組集合(需權限,可能拋異常)
process.Id / ProcessNamePID / 映像檔名(無副檔名)

完整掃描與終止範例

using System;
using System.Diagnostics;
using System.IO;

public class ProcessManager
{
    public void ListAndKillTarget(string targetExePath)
    {
        var processes = Process.GetProcesses();
        foreach (var p in processes)
        {
            if (p.Id == 0) continue; // 系統閒置進程

            string info = $"進程名稱: {p.ProcessName}  PID: {p.Id}";
            
            try
            {
                // Modules 需足夠權限,64位進程無法從32位應用存取,需 try-catch
                if (p.Modules.Count > 0)
                {
                    var mainModule = p.Modules[0];
                    info += $"\n  模組路徑: {mainModule.FileName}";
                    info += $"\n  模組名稱: {mainModule.ModuleName}";
                    info += $"\n  版本資訊: {mainModule.FileVersionInfo}";

                    // 比對完整路徑(忽略大小寫)
                    if (string.Equals(mainModule.FileName, targetExePath, StringComparison.OrdinalIgnoreCase))
                    {
                        Console.WriteLine($"[匹配] 正在終止: {info}");
                        p.Kill(); // 強制結束
                        p.WaitForExit(2000); // 等待結束
                        Console.WriteLine("已終止。");
                    }
                }
            }
            catch (System.ComponentModel.Win32Exception ex)
            {
                // 權限不足(如嘗試存取系統進程 csrss.exe 等)
                info += $"\n  [存取模組失敗] {ex.Message}";
            }
            catch (Exception ex)
            {
                info += $"\n  [其他錯誤] {ex.Message}";
            }
            finally
            {
                Console.WriteLine(info);
                Console.WriteLine(new string('=', 50));
            }
        }
    }
}

關鍵注意事項

1. 架構相容性(32/64 位)

  • 32 位應用(Prefer 32-bit 勾選)無法正確列舉 64 位進程的 `Modules`。
  • 解決:專案屬性 → Build → **取消勾選 "Prefer 32-bit"**,編譯為 64 位或 Any CPU (Prefer 32-bit=false)。

2. 權限與 UAC

  • 終止系統進程、他人會話進程需**管理員權限**。
  • 應用程式清單加入 ``。

3. Kill() vs CloseMainWindow()

方法行為適用場景
Kill()立即終止,核心對象直接移除,**資料遺失風險**無回應程式、服務、背景工作者、惡意程式清理
CloseMainWindow()發送 `WM_CLOSE` 訊息,**讓程式自行處理關閉邏輯**(儲存、確認對話框)有 GUI 的使用者應用程式

4. 進程名稱不含副檔名

`ProcessName` 回傳 "notepad" 而非 "notepad.exe"。比對時請用 `Path.GetFileNameWithoutExtension` 或直接比對 `Modules[0].FileName`。

5. 避免殺死自己

if (p.Id == Process.GetCurrentProcess().Id) continue;

進階:啟動進程並傳遞參數

var startInfo = new ProcessStartInfo
{
    FileName = "notepad.exe",
    Arguments = @"C:\temp\log.txt",
    WorkingDirectory = @"C:\temp",
    WindowStyle = ProcessWindowStyle.Maximized,
    UseShellExecute = true // 預設 true,支援 URL/文件關聯啟動
};
Process.Start(startInfo);

監控進程事件(非輪詢)

var watcher = new ManagementEventWatcher(
    new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace"));
watcher.EventArrived += (s, e) => 
    Console.WriteLine($"新進程: {e.NewEvent.Properties["ProcessName"].Value} PID: {e.NewEvent.Properties["ProcessID"].Value}");
watcher.Start();
// 停止時 watcher.Stop();

需引用 `System.Management`,適合即時監控而非定時掃描。

總結

`Process.GetProcesses()` + `Modules[0].FileName` 是精準識別目標程式的關鍵。務必處理架構相容、權限不足、例外捕獲三大坑點。生產環境建議優先 `CloseMainWindow()` 給予體面退出,`Kill()` 作為最後手段。大規模部署請考慮 WMI 事件訂閱替代輪詢,降低效能開銷。

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