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

Win10关机时如何自动终止常驻程序避免阻停并执行预设指令

Windows下自运行循环程序适配关机流程方案

Windows提供了原生的系统事件通知机制,可以在关机触发后、正式断电/重启前执行自定义收尾逻辑,让程序正常退出,不会弹出“程序阻止关机”的系统提示。

核心原理

  • 系统触发关机流程时,会按顺序向所有运行中的程序发送通知消息,预留固定时长供程序自行退出
  • 桌面类程序需要响应WM_QUERYENDSESSION、WM_ENDSESSION两个窗口消息,控制台程序可以通过监听控制台控制事件捕获关机信号
  • 收到关机信号后,主动终止while主循环、按顺序执行资源释放、数据保存等指定操作,最后正常退出进程即可,不需要额外调用系统关机接口
  • 系统默认给单程序预留的关机处理时长为5秒,自定义收尾逻辑不要包含长时间阻塞的操作,避免被系统强制终止

实现示例

1. 桌面类/无窗口Python程序实现

通过创建隐藏的消息窗口接收系统关机消息,不依赖第三方库:

import ctypes
import ctypes.wintypes
import threading
import time

# 全局运行标记,控制主循环状态
is_running = True

def shutdown_monitor():
    # 窗口消息处理回调
    def window_proc(hwnd, msg, wparam, lparam):
        global is_running
        # 收到关机查询消息,直接返回同意关机
        if msg == 0x0011:  # WM_QUERYENDSESSION
            return 1
        # 收到正式关机通知,执行自定义收尾逻辑
        if msg == 0x0016:  # WM_ENDSESSION
            if wparam:
                # 以下位置按顺序写需要在关机前执行的指令
                print("停止接收新业务请求")
                time.sleep(0.3)
                print("持久化内存中未保存的数据")
                time.sleep(0.3)
                print("释放端口、文件句柄等占用资源")
                # 修改循环标记,终止主服务循环
                is_running = False
            return 0
        return ctypes.windll.user32.DefWindowProcW(hwnd, msg, wparam, lparam)
    
    # 注册隐藏窗口用于接收系统消息
    h_instance = ctypes.windll.kernel32.GetModuleHandleW(None)
    wnd_class = ctypes.wintypes.WNDCLASSW()
    wnd_class.lpfnWndProc = ctypes.WINFUNCTYPE(
        ctypes.c_long, 
        ctypes.wintypes.HWND, 
        ctypes.wintypes.UINT, 
        ctypes.wintypes.WPARAM, 
        ctypes.wintypes.LPARAM
    )(window_proc)
    wnd_class.hInstance = h_instance
    wnd_class.lpszClassName = "ShutdownMonitorWin"
    ctypes.windll.user32.RegisterClassW(ctypes.byref(wnd_class))
    ctypes.windll.user32.CreateWindowExW(
        0, wnd_class.lpszClassName, "", 0,
        0, 0, 0, 0, 0, 0, h_instance, 0
    )

    # 启动消息循环监听系统事件
    msg = ctypes.wintypes.MSG()
    while ctypes.windll.user32.GetMessageW(ctypes.byref(msg), 0, 0, 0) != 0:
        ctypes.windll.user32.TranslateMessage(ctypes.byref(msg))
        ctypes.windll.user32.DispatchMessageW(ctypes.byref(msg))

# 启动关机监听守护线程
threading.Thread(target=shutdown_monitor, daemon=True).start()

# 原有的while循环服务逻辑
request_count = 0
while is_running:
    print(f"服务正常运行,累计处理请求数:{request_count}")
    request_count += 1
    time.sleep(1)

print("程序正常退出,不会阻断系统关机流程")

2. 控制台程序简易实现

如果你的程序是直接运行的控制台程序,可以用更简单的控制台事件监听方式:

import ctypes
import time

is_running = True

@ctypes.WINFUNCTYPE(ctypes.c_long, ctypes.c_ulong)
def console_ctrl_handler(ctrl_type):
    global is_running
    # 监听到系统关机事件
    if ctrl_type == 6:  # CTRL_SHUTDOWN_EVENT
        # 执行自定义收尾指令
        print("收到关机信号,准备退出")
        is_running = False
        return 1
    return 0

# 注册控制台事件回调
ctypes.windll.kernel32.SetConsoleCtrlHandler(console_ctrl_handler, 1)

# 原有while服务循环
while is_running:
    time.sleep(1)

优化建议

  • 如果是需要长期后台运行的服务类程序,建议封装为标准Windows系统服务,通过服务控制管理器的停止回调处理关机逻辑,稳定性更高,不会受前台程序超时规则限制
  • 收尾逻辑尽量精简,不要包含网络请求、大文件写入等耗时操作,避免超过系统预留的处理时间被强制杀死
  • 不要在关机回调中弹出交互对话框,会被系统判定为未响应程序,依然会触发阻断关机的提示

内容的提问来源于stack exchange,提问作者Mouad Essalim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 23:12:33