如何检测Windows系统重启/关机并在应用运行时执行指定操作?
Windows系统下捕获关机/重启信号并执行操作的正确实现
- 注册系统通知回调
Windows平台分控制台和GUI程序两种处理方式:- 控制台程序用
SetConsoleCtrlHandler注册回调,捕获关机、注销、窗口关闭等事件:
- 控制台程序用
#include <windows.h> #include <iostream> BOOL WINAPI ConsoleHandler(DWORD dwCtrlType) { switch(dwCtrlType) { case CTRL_SHUTDOWN_EVENT: // 系统关机/重启 case CTRL_LOGOFF_EVENT: // 用户注销 case CTRL_CLOSE_EVENT: // 窗口被关闭 // 替换成你的业务操作:保存数据、清理临时文件等 std::cout << "执行关机前操作..." << std::endl; // 注意:操作必须快,系统会强制终止超时进程,建议控制在10秒内 Sleep(2000); // 示例延迟,实际替换为真实逻辑 return TRUE; default: return FALSE; } } int main() { if (!SetConsoleCtrlHandler(ConsoleHandler, TRUE)) { std::cerr << "注册回调失败,错误码:" << GetLastError() << std::endl; return 1; } std::cout << "程序运行中,等待系统信号..." << std::endl; while (true) { Sleep(1000); // 保持进程存活 } return 0; }
- GUI程序需要在窗口过程中处理
WM_QUERYENDSESSION和WM_ENDSESSION消息:
#include <windows.h> DWORD WINAPI ShutdownOperation(LPVOID lpParam) { // 异步执行关机前操作,避免阻塞消息循环 // 比如保存用户配置、关闭网络连接 Sleep(2000); return 0; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_QUERYENDSESSION: // 系统询问是否允许关闭,返回TRUE同意 // 这里别做耗时操作,开线程处理 CreateThread(NULL, 0, ShutdownOperation, NULL, 0, NULL); return TRUE; case WM_ENDSESSION: // 系统即将关闭,做快速收尾 if (wParam == TRUE) { // 比如释放句柄、清理内存 } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; }
- 常见坑点排查
- 操作超时:Windows给进程的处理窗口很短(一般5-15秒),超时会被强制杀进程,务必把操作简化。
- 权限不足:如果要写系统目录、修改注册表,得确保程序以管理员权限运行,否则操作会静默失败。
- 回调注册失败:检查
SetConsoleCtrlHandler的返回值,失败时用GetLastError()查具体原因。 - 漏处理事件:别只盯
CTRL_SHUTDOWN_EVENT,用户注销(CTRL_LOGOFF_EVENT)也要覆盖到。
内容的提问来源于stack exchange,提问作者Poséidon
相关产品推荐
相关产品推荐

