.NET 透過 `System.Diagnostics.Process` 提供強大的進程列舉、資訊查詢、啟動與終止功能。本文詳細說明如何掃描系統進程、讀取模組路徑、版本資訊,並安全地終止指定進程,附帶完整 WinForms 範例代碼。
| 成員 | 用途 |
|---|---|
Process.GetProcesses() | 取得所有進程陣列(含系統進程) |
Process.GetProcessesByName(name) | 依名稱篩選(不含 .exe) |
Process.Start(startInfo) | 啟動新進程 |
process.Kill() | 強制終止(不給儲存機會) |
process.CloseMainWindow() | 優雅關閉(發送 WM_CLOSE,僅限有視窗進程) |
process.Modules | 載入模組集合(需權限,可能拋異常) |
process.Id / ProcessName | PID / 映像檔名(無副檔名) |
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));
}
}
}
}
| 方法 | 行為 | 適用場景 |
|---|---|---|
Kill() | 立即終止,核心對象直接移除,**資料遺失風險** | 無回應程式、服務、背景工作者、惡意程式清理 |
CloseMainWindow() | 發送 `WM_CLOSE` 訊息,**讓程式自行處理關閉邏輯**(儲存、確認對話框) | 有 GUI 的使用者應用程式 |
`ProcessName` 回傳 "notepad" 而非 "notepad.exe"。比對時請用 `Path.GetFileNameWithoutExtension` 或直接比對 `Modules[0].FileName`。
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 事件訂閱替代輪詢,降低效能開銷。