• Windows 7下阻止系统关机 分类: windows驱动程序WDM 2014-04-29 14:43 562人阅读 评论(1) 收藏


    从Vista开始,想阻止系统关机就开始变麻烦了,不能只拦截WM_QUERYENDSESSION了,操作系统只给一个应用程序两秒钟的时间去保存自己的东西,两秒钟之后,不管做完了没有,Game Over!可是如果你正在刻录一张光盘呢?两秒钟是都不够的,所以Vista之后也给提供了一种方式阻止系统关机,就是ShutdownBlockReasonCreate函数,只要调用这个函数,第一个参数传递创建主窗口的句柄,第二个参数传递一个字符串,这个字符串说明阻止关机的原因,将会显示给用户。而且msdn提示说这个API函数只能由创建主窗口的线程调用,否则将返回ERROR_ACCESS_DENIED。而且完成后还得调用ShutdownBlockReasonDestroy函数使系统关机能够继续进行,参数只传递上面那个窗口的句柄就可以了。

      下面这段代码就是完整实现,不能使用VS2005编译,因为自带的库还没有这俩函数,我是使用VS2010编译的,工程文件和可执行文件的下载地址在文章最下方。

    复制代码
      1 #include <windows.h>
      2 #include <tchar.h>
      3 #include "resource.h"
      4 
      5 //标记是否已经阻止关机,默认为未阻止
      6 BOOL blockedFlag = FALSE;
      7 
      8 //这俩函数纯粹是撒娇,为了突出它们才拿出来改个名的
      9 BOOL BlockShutdown(HWND hwnd)
     10 {
     11     if (ShutdownBlockReasonCreate(hwnd, _T("不准关机!除非你点强制关机 :-(")))
     12     {
     13         return TRUE;
     14     }
     15     return FALSE;
     16 }
     17 
     18 BOOL UnblockShutdown(HWND hwnd)
     19 {
     20     if (ShutdownBlockReasonDestroy(hwnd))
     21     {
     22         return TRUE;
     23     }
     24     return FALSE;
     25 }
     26 
     27 INT_PTR CALLBACK MainDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
     28 {
     29     switch(uMsg)
     30     {
     31     case WM_INITDIALOG:
     32         SetDlgItemText(hwndDlg, IDC_STATIC_STATUS, _T("未阻止关机"));
     33         return TRUE;
     34     case WM_CLOSE:
     35         if (blockedFlag)
     36         {
     37             if (UnblockShutdown(hwndDlg))
     38             {
     39                 EndDialog(hwndDlg, 0);
     40                 return TRUE;
     41             }
     42             if (IDYES == MessageBox(hwndDlg, _T("解除阻止失败……还要继续关闭程序么(关闭程序后不影响关机)?"), _T("提示"), MB_YESNO))
     43             {
     44                 EndDialog(hwndDlg, 0);
     45                 return TRUE;
     46             }
     47             return FALSE;
     48         }
     49         EndDialog(hwndDlg, 0);
     50         return TRUE;
     51     case WM_QUERYENDSESSION:
     52         if (blockedFlag)        //不要以为只调用BlockShutdownReasonCreate就行了,WM_QUERYENDSESSION也得拦住
     53         {
     54             return TRUE;
     55         }
     56         return FALSE;
     57     case WM_COMMAND:
     58         switch(LOWORD(wParam))
     59         {
     60         case IDC_BUTTON_BLOCK:
     61             if (blockedFlag)
     62             {
     63                 MessageBox(hwndDlg, _T("已经阻止关机,请点击关机测试。"), _T("提示"), MB_OK);
     64             }
     65             else
     66             {
     67                 if (BlockShutdown(hwndDlg))
     68                 {
     69                     SetDlgItemText(hwndDlg, IDC_STATIC_STATUS, _T("已经阻止关机"));
     70                     blockedFlag = TRUE;
     71                 }
     72                 else
     73                 {
     74                     MessageBox(hwndDlg, _T("阻止关机失败了……"), _T("提示"), MB_OK);
     75                 }
     76             }
     77             return TRUE;
     78         case IDC_BUTTON_UNBLOCK:
     79             if (!blockedFlag)
     80             {
     81                 MessageBox(hwndDlg, _T("未阻止关机,无需解除。"), _T("提示"), MB_OK);
     82             }
     83             else
     84             {
     85                 if (UnblockShutdown(hwndDlg))
     86                 {
     87                     SetDlgItemText(hwndDlg, IDC_STATIC_STATUS, _T("未阻止关机"));
     88                     blockedFlag = FALSE;
     89                 }
     90                 else
     91                 {
     92                     MessageBox(hwndDlg, _T("解除阻止失败了……"), _T("提示"), MB_OK);
     93                 }
     94             }
     95             return TRUE;
     96         default:
     97             return FALSE;
     98         }
     99     default:
    100         return FALSE;
    101     }
    102     return FALSE;
    103 }
    104 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
    105 {
    106     DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAINDIALOG), NULL, MainDialogProc);
    107     return 0;
    108 }
    复制代码

      下图就是运行效果。

    ShutdownBlocker

      上面这个图应该很多人看到过,只是通常刚一显示就消失了,这样就不会消失了,直到程序调用了ShutdownBlockReasonDestroy。

      还有一点需要注意的是,如果你的电脑安装了360安全卫士orQQ电脑管家等优化软件,通常都会一键优化给优化掉……你就看不到这个对话框了,程序直接被枪毙掉了,因为这样可以加快关机速度 :-(

      完整的C语言工程和可执行程序文件都在压缩包里,为了方便没装VS2010的童鞋测试程序效果,msvcr100.dll我也放到release目录下了,下载地址是http://files.cnblogs.com/pianoid/ShutdownBlocker.rar

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    Difference between application/xml and text/xml
    [转]ASP.NET MVC URL 路由简介
    js Unicode编码转换
    svn更改用户名
    招商银行开发成功国内业界第一个实用的数据仓库系统
    Response.ContentType 详细列表备忘使用(转载)
    WebClient UploadData UploadFile 用法
    char tchar wchar_t WCHAR LPCTSTR LPCWSTR
    网站测试自动化系统—系统应该有的功能
    网站测试自动化系统—收集测试结果
  • 原文地址:https://www.cnblogs.com/mao0504/p/4706631.html
Copyright © 2020-2023  润新知