阻止windows关机时自动结束进程,导致数据丢失或异常

您所在的位置:网站首页 电脑关机时提示有程序未关闭然后取消了导致白屏 阻止windows关机时自动结束进程,导致数据丢失或异常

阻止windows关机时自动结束进程,导致数据丢失或异常

2023-08-12 00:53| 来源: 网络整理| 查看: 265

windows在结束对话或者一个系统关机的时候,系统会发送WM_QUERYENDSESSION消息给尚未终止的所有窗口。当程序在处理这个消息的时候,如果返回了false,那么系统将不结束对话或者关机(注销)。 需要注意在XP里面,我们直接返回false,可以做到阻止关机的作用,但是在Windows Vista及在这之后的操作系统,直接返回false无法达到阻止关机的效果。需要借助两个函数ShutdownBlockReasonCreate和ShutdownBlockReasonDestroy XP里面处理比较简单,所以这里主要说Vista之后的操作系统 可以把整个处理分成几个部分:

1.当我们的程序收到系统的WM_QUERYENDSESSION函数时,返回false,并且使用ShutdownBlockReasonCreate弹提示说明关机被打断的原因 2.向系统安装钩子处理控制台消息(初始化的时候) 3.过滤控制台消息,如果用户强制关机,发送WM_CLOSE给我们的程序 4.这时候我们调用ShutdownBlockReasonDestroy让关机继续进行

这种代码网上很多,这里附上我整理的相关函数,全部代码和别的代码混在一起,太乱

这是处理控制台的钩子函数

BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType) { // 用户按下CTRL+BREAK, 或者由GenerateConsoleCtrlEvent API发出,当试图关闭控制台程序,系统发送关闭消息。 if (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT || dwCtrlType == CTRL_CLOSE_EVENT) { SendMessage(hWnd, WM_CLOSE, 0, 0); return TRUE; } return FALSE; }

注册窗口类

void register (HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)procWndMsg; //回调函数 wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.lpszMenuName = NULL; wcex.lpszClassName = L"TestClass"; wcex.hIconSm = NULL; // 安装钩子处理控制台消息 SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleCtrlHandler, TRUE);

创建窗口类

BOOL creatWindow(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; RECT sz = {0, 0, 512, 512}; AdjustWindowRect(&sz, WS_OVERLAPPEDWINDOW, TRUE); hWnd = CreateWindow(L"TestClass", L"Test Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, sz.right - sz.left, sz.bottom - sz.top, NULL, NULL, hInstance, NULL); if(!hWnd) { return FALSE; } }

处理信息回调函数

LRESULT CALLBACK procWndMsg(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; switch(message) { case WM_QUERYENDSESSION: if (ncOSUtil::IsWinXPFamily ()){ static BOOL bFlag = FALSE; if (bFlag) { return TRUE; } //这里建议弹出个等待窗口来提示,因为XP没有还有进程未关闭那个界面 bFlag = TRUE; return FALSE; } else { return FALSE; } break; case WM_CREATE: if (!ncOSUtil::IsWinXPFamily ()) { //这里使用函数指针来调用,否则在XP下,USER32里面没有这两个函数,会无法找到入口 //即使用if不进入这里也会报错,亲测 typedef BOOL (WINAPI* SHUTDOWNBLOCKREASONCREATE) (__in HWND hWnd, __in LPCWSTR pwszReason); HMODULE hUser32Dll = GetModuleHandle (_T("User32")); SHUTDOWNBLOCKREASONCREATE pShutdownBlockReasonCreate = (SHUTDOWNBLOCKREASONCREATE)GetProcAddress (hUser32Dll, "ShutdownBlockReasonCreate"); if (pShutdownBlockReasonCreate) { pShutdownBlockReasonCreate (hwnd, L"程序正在运行,建议手动关闭后在关机或注销,以免引起数据丢失。"); //弹提示,阻止关机 } } break; case WM_DESTROY: if (!ncOSUtil::IsWinXPFamily ()) { typedef BOOL (WINAPI* SHUTDOWNBLOCKREASONDESTROY) (__in HWND hWnd); HMODULE hUser32Dll = GetModuleHandle (_T("User32")); SHUTDOWNBLOCKREASONDESTROY pShutdownBlockReasonDestroy = (SHUTDOWNBLOCKREASONDESTROY)GetProcAddress (hUser32Dll, "ShutdownBlockReasonDestroy"); if (pShutdownBlockReasonDestroy) { pShutdownBlockReasonDestroy (hwnd); //继续关机 } PostQuitMessage (0); //退出消息循环 } break; default: break; } return TRUE; } 当然了,如果你是单独做一个这个小程序,完全可以不向系统安装钩子,直接循环获取消息,类似于这样 MSG msg; while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; 经过我的测试,发现如果电脑上用优化软件优化了系统性能,会杀掉我的软件,无法阻止关机,解决办法和这个分开写


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3