直接调用 process.getprocesses() 可获取当前系统所有可见进程的 process 对象数组,但受限于权限,无法访问其他用户会话或保护进程,且不抛异常;需配合 wmi 或提升权限才能获得更全视图。

怎么用 Process.GetProcesses() 获取所有进程列表
直接调用 Process.GetProcesses() 就能拿到当前系统所有进程的 Process 对象数组,但要注意它不包含权限受限的进程(比如其他用户会话中的保护进程、系统服务进程),也不会抛异常——只是“看不见”。如果需要更全的视图,得配合 WMI 或提升权限运行程序。
常见误操作是直接遍历后取 Process.ProcessName 做字符串比较,结果遇到大小写不一致或带扩展名(如 chrome.exe vs Chrome)就漏匹配。建议统一转小写再比:
var processes = Process.GetProcesses(); var chromeProcs = processes.Where(p => p.ProcessName.ToLower() == "chrome").ToArray();
为什么 Kill() 有时失败并抛出 Win32Exception
Kill() 本质是向进程发送 TerminateProcess 系统调用,失败通常是因为权限不足或目标已退出。典型错误信息是:Access is denied(权限不够)、No such process(进程已死但对象未释放)、Attempted to read or write protected memory(极少见,多因进程处于僵死状态)。
安全做法是先检查 HasExited,再调用 Kill(),并捕获 InvalidOperationException 和 Win32Exception:
- 以管理员身份运行你的 C# 程序才能结束系统级进程(如
svchost.exe、lsass.exe) -
Kill()是强制终止,不会给进程清理资源的机会;如需优雅退出,应优先尝试CloseMainWindow()+ 等待WaitForExit(3000) - 某些进程(如被调试器附加的、设置了作业对象的)可能拒绝被
Kill()
如何安全结束多个同名进程(比如全部 notepad.exe)
不能简单循环 Kill(),因为杀掉一个后,后续数组里的 Process 对象可能已失效(HasExited == true),再调用 Kill() 会触发 InvalidOperationException。
推荐做法:先收集 PID 或快照,再逐个处理:
var pids = Process.GetProcessesByName("notepad")
.Where(p => !p.HasExited)
.Select(p => p.Id)
.ToArray();
<p>foreach (var pid in pids) {
try {
var p = Process.GetProcessById(pid);
if (!p.HasExited) p.Kill();
}
catch (ArgumentException) { /<em> 进程已消失 </em>/ }
catch (InvalidOperationException) { /<em> 已退出或无权限 </em>/ }
catch (Win32Exception) { /<em> 拒绝访问等系统错误 </em>/ }
}</p>
注意:GetProcessesByName() 返回的是实时引用,不是快照,所以必须在调用后立刻检查 HasExited,否则容易踩空指针类异常。
结束进程时最容易被忽略的细节
一是没处理 UAC 权限问题——即使你代码里写了 app.manifest 并设了 requireAdministrator,VS 调试时默认不提权,得手动右键“以管理员身份运行”调试器;二是混淆了 ProcessName 和 MainWindowTitle,比如想关“微信”,但 ProcessName 实际是 WeChat,而标题栏文字才是“微信”,后者无法用于 Kill();三是忘了释放 Process 对象,长期运行的监控程序若反复调用 GetProcesses() 又不 Dispose(),会导致句柄泄漏。
真正稳定的做法:用 PID 做唯一标识,结合 try/catch 容错,且每次操作前确认权限和存活状态。










