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

来源:互联网 发布:win访问mac共享文件夹 编辑:程序博客网 时间:2024/06/06 12:42

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;

经过我的测试,发现如果电脑上用优化软件优化了系统性能,会杀掉我的软件,无法阻止关机,解决办法和这个分开写

阅读全文
0 0
原创粉丝点击