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

Windows服务关机时未调用OnStop()和OnShutdown()方法的解决咨询

解决Windows服务在Fast Startup关机时无法触发OnShutdown/OnStop的问题

问题根源

Windows的Fast Startup(快速启动)本质是系统休眠机制:关机时系统将内核状态写入hiberfil.sys文件,下次启动直接加载该文件恢复系统,而非执行完整的关机流程。这种情况下,服务控制管理器(SCM)不会发送SERVICE_CONTROL_SHUTDOWN通知,因此你的OnShutdown和OnStop方法不会被触发。

可行解决方案

1. 禁用Fast Startup(最直接)

通过修改注册表或系统设置关闭快速启动,让系统执行完整关机流程:

  • 注册表修改(需管理员权限):
    编辑HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Power路径下的HiberbootEnabled DWORD值,设为0。
    你可以在服务安装程序中添加这段逻辑,或让用户手动在「电源选项」→「选择电源按钮的功能」→「更改当前不可用的设置」中取消勾选「启用快速启动」。

2. 监听系统休眠事件(服务内处理)

Fast Startup触发的是系统休眠,因此可以通过重写服务的OnPowerEvent方法监听休眠请求,在此时执行清理逻辑:
修改你的服务代码,添加以下内容:

namespace SimpleService
{
    class TestService : ServiceBase
    {
        private string path = "<pathtologfile>\\TestServiceLog.txt";
        public TestService()
        {
            this.ServiceName = "TestService";
            // 必须设置此属性,否则OnPowerEvent不会被调用
            this.CanHandlePowerEvent = true;
        }

        protected override void OnStart(string[] args)
        {
           
        }

        protected override void OnStop()
        {
            WriteLog("TestService Stopped.");
        }

        protected override void OnShutdown()
        {
            OnStop();
        }

        // 处理电源事件
        protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus)
        {
            if (powerStatus == PowerBroadcastStatus.QuerySuspend)
            {
                // Fast Startup触发的休眠会进入此分支
                WriteLog("TestService is suspending (Fast Startup shutdown).");
                // 返回true表示允许系统休眠
                return true;
            }
            return base.OnPowerEvent(powerStatus);
        }

        // 封装日志写入逻辑,避免重复代码
        private void WriteLog(string message)
        {
            using (StreamWriter sw = File.AppendText(path))
            {
                sw.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - {message}");
            }
        }
    }
}

注意:QuerySuspend事件可能会被系统取消(比如用户取消休眠),如果你的操作需要确保执行,可以监听Suspend事件,但系统留给服务的执行时间有限,务必保证操作快速完成。

3. 使用任务计划程序(独立执行)

创建一个任务计划,监听系统休眠/关机的事件ID,触发时执行你的清理逻辑:

  • 触发器选择「系统事件」,事件日志选「系统」,来源选「Kernel-Power」,事件ID填42(系统进入休眠)或1074(用户发起关机)。
  • 操作选择「启动程序」,指向一个独立的控制台程序(或脚本),执行你需要的清理/日志操作。
    这种方式的优势是即使服务未运行,也能执行操作,但需要管理员权限配置任务计划。

方案选择建议

  • 如果可以接受牺牲启动速度,优先选方案1,彻底解决问题;
  • 如果必须支持Fast Startup,选方案2,在服务内完成逻辑,无需额外组件;
  • 如果需要脱离服务独立执行操作,选方案3。

内容的提问来源于stack exchange,提问作者Mohd Ahmed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 10:53:30