You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中检测进程被终止?含Windows服务场景技术问询

嘿,我来帮你梳理清楚这个问题!你需要的是在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:04:09