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

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

 #include <windows.h>
 #include <tchar.h>
 #include "resource.h"

 //标记是否已经阻止关机,默认为未阻止
 BOOL blockedFlag = FALSE;

 //这俩函数纯粹是撒娇,为了突出它们才拿出来改个名的
 BOOL BlockShutdown(HWND hwnd)
 {
     if (ShutdownBlockReasonCreate(hwnd, _T("不准关机!除非你点强制关机 :-(")))
     {
         return TRUE;
     }
     return FALSE;
 }

 BOOL UnblockShutdown(HWND hwnd)
 {
     if (ShutdownBlockReasonDestroy(hwnd))
     {
         return TRUE;
     }
     return FALSE;
 }

 INT_PTR CALLBACK MainDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
     switch(uMsg)
     {
     case WM_INITDIALOG:
         SetDlgItemText(hwndDlg, IDC_STATIC_STATUS, _T("未阻止关机"));
         return TRUE;
     case WM_CLOSE:
         if (blockedFlag)
         {
             if (UnblockShutdown(hwndDlg))
             {
                 EndDialog(hwndDlg, );
                 return TRUE;
             }
             if (IDYES == MessageBox(hwndDlg, _T("解除阻止失败……还要继续关闭程序么(关闭程序后不影响关机)?"), _T("提示"), MB_YESNO))
             {
                 EndDialog(hwndDlg, );
                 return TRUE;
             }
             return FALSE;
         }
         EndDialog(hwndDlg, );
         return TRUE;
     case WM_QUERYENDSESSION:
         if (blockedFlag)        //不要以为只调用BlockShutdownReasonCreate就行了,WM_QUERYENDSESSION也得拦住
         {
             return TRUE;
         }
         return FALSE;
     case WM_COMMAND:
         switch(LOWORD(wParam))
         {
         case IDC_BUTTON_BLOCK:
             if (blockedFlag)
             {
                 MessageBox(hwndDlg, _T("已经阻止关机,请点击关机测试。"), _T("提示"), MB_OK);
             }
             else
             {
                 if (BlockShutdown(hwndDlg))
                 {
                     SetDlgItemText(hwndDlg, IDC_STATIC_STATUS, _T("已经阻止关机"));
                     blockedFlag = TRUE;
                 }
                 else
                 {
                     MessageBox(hwndDlg, _T("阻止关机失败了……"), _T("提示"), MB_OK);
                 }
             }
             return TRUE;
         case IDC_BUTTON_UNBLOCK:
             if (!blockedFlag)
             {
                 MessageBox(hwndDlg, _T("未阻止关机,无需解除。"), _T("提示"), MB_OK);
             }
             else
             {
                 if (UnblockShutdown(hwndDlg))
                 {
                     SetDlgItemText(hwndDlg, IDC_STATIC_STATUS, _T("未阻止关机"));
                     blockedFlag = FALSE;
                 }
                 else
                 {
                     MessageBox(hwndDlg, _T("解除阻止失败了……"), _T("提示"), MB_OK);
                 }
             }
             return TRUE;
         default:
             return FALSE;
         }
     default:
         return FALSE;
     }
     return FALSE;
 }
 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
 {
     DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAINDIALOG), NULL, MainDialogProc);
     ;
 }

  下图就是运行效果。

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

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

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

Windows 7下阻止系统关机的更多相关文章

  1. Windows/Linux下查看系统CPU使用最高的线程

    参考:https://blog.csdn.net/qq_27818157/article/details/78688580 jstack -l 31372 > c:/31372.stack

  2. ubuntu18.04 & Windows10 双系统关机缓慢

    1.Windows与Ubuntu双系统关机缓慢并不少见,有时单系统下的Linux mint或Ubuntu都会出现这个现象.主要原因是还有没有关闭的进程或者是软件兼容的原因,所以导致每次关机都有一个90 ...

  3. C#实现控制Windows系统关机、重启和注销的方法:

    shutdown命令的参数: shutdown.exe -s:关机shutdown.exe -r:关机并重启shutdown.exe -l:注销当前用户 shutdown.exe -s -t 时间:设 ...

  4. C#实现控制Windows系统关机、重启和注销的方法

    shutdown命令的参数: shutdown.exe -s:关机shutdown.exe -r:关机并重启shutdown.exe -l:注销当前用户 shutdown.exe -s -t 时间:设 ...

  5. 如何在Windows Server 2008 R2没有磁盘清理工具的情况下使用系统提供的磁盘清理工具

    今天,刚好碰到服务器C盘空间满的情况,首先处理了临时文件和有关的日志文件后空间还是不够用,我知道清理C盘的方法有很多,但今天只分享一下如何在Windows Server 2008 R2没有磁盘清理工具 ...

  6. Windows 7/8/10 系统下Laravel框架的开发环境安装及部署详解(Vagrant + Homestead)

    注意! laravel/homestead box项目地址已经不再是原来的 https://atlas.hashicorp.com/laravel/boxes/homestead 而已经变更成 htt ...

  7. Windows和Linux双系统下完美卸载linux

    装了Windows和linux双系统的朋友,在后期要删除linux是个比较头痛的问题,因为MBR已经被linux接管,本文的目的是如何在windows 和linux双系统下,简单,完美地卸载linux ...

  8. 如何在Windows环境下安装Linux系统虚拟机

    如何在Windows环境下安装Linux系统虚拟机 本篇经验写给想要入门学习C语言的小白们.Windows系统因为使用窗口图形化,操作简单,功能多样,所以我们在Windows环境下可以做到很多,但想要 ...

  9. 使用PHPstudy在Windows服务器下部署PHP系统

    PHP网站一般运行在Apache服务器上,IIS服务器上也可以运行,但是不推荐,windows服务器上没有集成Apache跟PHP的运行环境,但是借助第三方的软件就能很好的搞定,一般这样的软件有很多, ...

随机推荐

  1. C#基础(三)--运算符及条件控制语句

    上一章我们了解了C#的一些数据基本类型.如何定义使用变量及类型之间的相互转换.可能大家会发现程序只能按照我们的要求从上向下这样顺序一条一条的执行. 那么程序能按照我们的要求,当某个条件成立的时候才执行 ...

  2. Selenium UI自动化解决iframe定位问题

      更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢! 原文链接:http://www.cnblogs.com/zishi/p/6735116.html 一个阴雨霏霏 ...

  3. C# 实现Html转JSON

    Html为树结构->Json为数组结构 应用场景 H5或浏览器展示Html代码没有问题,但是让原生APP或ReactNative直接展示Html可能会有很多不便 实现方法 可以通过正则表达式捕获 ...

  4. cglib应用

    JDK的动态代理,经常被用来动态地创建对象的代理.JDK的动态代理用起来非常简单,但是有一个限制,就是使用动态代理的对象必须实现一个或多个接口.如果想代理没有实现接口,还可以使用cglib包来完成代理 ...

  5. 为什么webstrom无法格式化代码?

    用过webstrom的童鞋都知道格式化代码需要按快捷键:ctrl+Alt+L:可是我最近发现这个快捷键不管用,今天终于知道了原因, 是后台网易云音乐没有关,和网易云音乐的快捷键冲突了,就是这么神奇没办 ...

  6. [偏序关系与CDQ分治]【学习笔记】

    组合数学真是太棒了 $CDQ$真是太棒了(雾 参考资料: 1.<组合数学> 2.论文 课件 很容易查到 3.sro __stdcall 偏序关系 关系: 集合$X$上的关系是$X$与$X$ ...

  7. DNA序列局部比对(Smith–Waterman algorithm)

    生物信息原理作业第三弹:DNA序列局部比对,利用Smith–Waterman算法,python3.6代码实现. 实例以及原理均来自https://en.wikipedia.org/wiki/Smith ...

  8. 让SpringMVC Restful API优雅地支持多版本

    好久没有更新博客,难得有空,记录一下今天写的一个小工具,供有需要的朋友参考. 在移动APP开发中,多版本接口同时存在的情况经常发生,通常接口支持多版本,有以下两种方式: 1.通过不同路径区分不同版本 ...

  9. [代码]JAVA触发器,Spring的quartz配置

    Spring的quartz中的配置代码,spring-quartz.xml: <?xml version="1.0" encoding="UTF-8"?& ...

  10. python中的变量,运算符

    范例: name = 'Crossin' myVar = 123 price = 5.99 visible = True “=”的作用是把右边的值赋予给左边的变量. python中有四种较为常见的数据 ...