如何在C#中检测进程被终止?含Windows服务场景技术问询
嘿,我来帮你梳理清楚这个问题!你需要的是在C#里检测进程(尤其是Windows服务)被终止的事件,从而执行清理操作,先区分清楚检测终止和阻止终止的区别,再给你具体的实现方案:
一、常规Windows服务的正常停止处理
如果是通过服务控制台、sc stop命令这类正常方式停止服务,Windows服务框架本身就提供了现成的方法——重写OnStop(),你可以在这里执行所有清理逻辑:
protected override void OnStop() { // 在这里写你的停止处理逻辑:保存状态、关闭资源、停止后台线程等等 Logger.Info("服务正在正常停止,开始执行清理操作..."); // 示例:终止后台工作线程 _backgroundWorker?.CancelAsync(); // 示例:关闭数据库连接 _dbConnection?.Close(); }
⚠️ 注意:如果进程是被强制终止的(比如任务管理器右键结束进程、taskkill /f命令),这个方法不会触发,因为系统直接终止了进程,没给服务执行代码的机会。
二、捕获强制终止/系统级终止事件
要应对强制终止的场景,需要用到Windows底层API来监听终止信号:
方法1:用SetConsoleCtrlHandler监听终止信号
这个API可以捕获控制台关闭、系统关机、用户注销等多种终止信号,适用于控制台应用和Windows服务:
using System; using System.Runtime.InteropServices; public static class TerminationHandler { // 定义回调委托 private delegate bool ConsoleCtrlHandler(CtrlTypes ctrlType); private enum CtrlTypes { CTRL_C_EVENT = 0, CTRL_BREAK_EVENT = 1, CTRL_CLOSE_EVENT = 2, // 窗口关闭/进程被终止 CTRL_LOGOFF_EVENT = 5, CTRL_SHUTDOWN_EVENT = 6 // 系统关机 } [DllImport("kernel32.dll", SetLastError = true)] private static extern bool SetConsoleCtrlHandler(ConsoleCtrlHandler handler, bool add); // 注册终止回调 public static void Register() { SetConsoleCtrlHandler(OnTerminationDetected, true); } // 终止事件触发时执行的逻辑 private static bool OnTerminationDetected(CtrlTypes ctrlType) { switch (ctrlType) { case CtrlTypes.CTRL_CLOSE_EVENT: case CtrlTypes.CTRL_SHUTDOWN_EVENT: case CtrlTypes.CTRL_LOGOFF_EVENT: Console.WriteLine("检测到进程终止信号!开始执行紧急清理..."); // 这里添加你的紧急处理代码:保存临时数据、通知依赖服务等 break; } return true; // 返回true表示已处理该事件 } }
对于Windows服务,你可以在OnStart方法里调用TerminationHandler.Register()来完成注册。
方法2:服务专属的SessionChange事件
如果你开发的是Windows服务,还可以重写OnSessionChange方法来捕获用户注销、系统关机这类系统级事件:
protected override void OnSessionChange(SessionChangeDescription changeDescription) { base.OnSessionChange(changeDescription); switch (changeDescription.Reason) { case SessionChangeReason.SessionLogoff: case SessionChangeReason.SystemShutdown: Logger.Info("检测到系统关机/用户注销,执行服务清理..."); // 执行你的清理逻辑 break; } }
三、关于你提供的“不可杀进程”代码
你贴的Unkillable类是通过RtlSetProcessIsCritical把进程标记为系统关键进程——这时候如果有人试图终止它,Windows会直接蓝屏崩溃,这是杀毒软件这类安全软件常用的自我保护手段,但这不是检测终止事件,而是直接阻止进程被终止。
如果你只是想在终止前执行清理,完全不需要用这个方法,它太极端还可能影响系统稳定性;但如果确实要实现类似杀毒软件的自我保护,这个方法是可行的,但要注意:
- 必须调用
Process.EnterDebugMode()获取调试权限 - 这个API是未公开的,未来Windows版本可能会修改
- 滥用会导致系统不稳定
总结
- 正常停止服务:用
OnStop()就够了 - 捕获强制终止/系统事件:用
SetConsoleCtrlHandler或OnSessionChange - 阻止进程被终止:用你提供的
RtlSetProcessIsCritical方法(谨慎使用)
内容的提问来源于stack exchange,提问作者Ardy

