WM_QUERYENDSESSION消息是Windows向你询问Windows能否关闭,WM_ENDSESSION消息表示提示你Windows即将关闭。故当应用程序退出时, WM_QUERYENDSESSION消息和WM_ENDSESSION消息均不响应。也就是说也就是说,你的程序在运行状态时,而系统由于某种原因需要注销或重启(或关机),此时操作系统会向你询问,但到你的同意(返回TRUE)后,系统才能做进一步的操作。


Windows 在注销、重起、关机之前会向每个当前正在运行的应用程序发送WM_QUERYENDSESSION消息,
--> 如果该应用程序方便关闭的话,则在此消息的消息响应函数OnQueryEndSession()中返回非0值(TRUE),否则返回0值(FALSE)。
--> 如果当前系统正在运行的应用程序全部返回非0值,则Windows的注销、重起、关机过程继续下去,并且向所有运行的应用程序发送WM_ENDSESSION消息,并且消息参数为TRUE;
--> 如果当前系统正在运行的应用程序其中之一返回0值,则Windows的注销、重起、关机过程被终止,并且不再继续对剩余的应用程序调用OnQueryEndSession()消息响应函数,而是向已经调用过了OnQueryEndSession()消息响应函数的应用程序发送WM_ENDSESSION消息,并且消息参数为FALSE。
所以一个应用程序只要响应WM_ENDSESSION消息,并在WM_ENDSESSION消息的消息响应函数OnEndSession(BOOL bEnding) 中根据参数bEnding来判断系统最后是否真的要注销、重起、关机了,然后做出适当的反应即可。
 
 
MSDN:

The framework calls this member function when the user chooses to end the Windows session or when an application calls theExitWindows Windows function. If any application returns 0, the Windows session is not ended. Windows stops callingOnQueryEndSession as soon as one application returns 0 and sends theWM_ENDSESSION message with a parameter value ofFALSE for any application that has already returned nonzero.

当用户选择关闭Windows或者应用程序调用Windows的ExitWindows函数时,框架调用这个成员函数。如果应用程序返回0,则Windows会话不会结束。只要有一个应用程序返回了0,Windows就停止调用OnQueryEndSession,并且向所有已经返回非零值的应用程序发送一个WM_ENDSESSION消息,参数值为FALSE。

目的:当用户注销系统的时候,注销前,让我的程序执行几行代码(释放资源/关闭端口之类的)。

思路:就跟把系统注销、重启和关机的消息都拦截下来,并销毁掉,不让其执行注销、重启和关机等操作原理是一样的。因为Windows在注销、重起、关机之前会向每个当前正在运行的应用程序广播一个消息WM_QUERYENDSESSION, 其lParam参数可以区分是关机还是注销用户(注销用户时lParam是ENDSESSION_LOGOFF)。然后Windows会等到所有的应用程序都对这个消息返回TRUE才会关机,因此,只要我们的应用程序对这个消息的处理返回FALSE,Windows就不会关机了。当系统注销的时候,所有非系统级的程序都会被退出,如果想让自己的程序在注销时仍然可以运行,就将自己的程序做成系统服务程序。

解决途径:拦截系统广播出来的WM_ENDSESSION和WM_QUERYENDSESSION消息。插一句:方法应该不止一种,比如系统钩子,但是参考网友的解决方案,程序一运行系统就奔溃了。没想到在MFC里面非常容易的通过重载WindowProc就可以实现,方法如下。

在MFC中的解决方法:

环境:VS 6.0, XP 32-bit

“查看”-->"建立类向导...",将WindowProc重载。

其函数体如下:

[cpp] view plain copy

  1. LRESULT CLabRelayDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
  2. {
  3. // TODO: Add your specialized code here and/or call the base class
  4. // WM_QUERYENDSESSION消息是Windows向你询问Windows能否关闭
  5. // WM_ENDSESSION消息表示提示你Windows即将关闭。
  6. switch(message) {
  7. case WM_ENDSESSION:
  8. // 把消息销毁掉,不让其正确转发。
  9. //message = WM_USERMESSAGE_NULL;
  10. //turn off the relay
  11. if(relayState==RELAY_ON)
  12. turnOff();
  13. break ;
  14. case WM_QUERYENDSESSION: //注销/关机
  15. //turn off the relay
  16. if(relayState==RELAY_ON)
  17. turnOff();
  18. break ;
  19. }
  20. return CDialog::WindowProc(message, wParam, lParam);
  21. }

就这样,系统注销的时候我的函数turnOff();被执行了。

关于lParam参数是通知码有一些的值:

ENDSESSION_CLOSEAPP 
0x00000001

The application is using a file that must be replaced, the system is being serviced, or system resources are exhausted. For more information, see Guidelines for Applications.

ENDSESSION_LOGOFF 
0x80000000

MFC: 获得关机消息;阻止Windows关机的更多相关文章

  1. 桌面程序阻止Windows关机(使用Message.Result取得DefWindowProc API函数的返回值,非常重要)

    Windows Client 客户端在关机,不外乎两种情况: 1. 没有处理 Windows 关机消息: 2.处理了关机消息,但是超时了: 上面这两种情况,都会让Windows 关不了机.在现实生活中 ...

  2. Windows关机过程分析与快速关机

    原文链接:http://blog.csdn.net/flyoxs/article/details/3710367 Windows开机和关机慢,很多时候慢得令人抓狂.特别是做嵌入式开发时(如XPE和Wi ...

  3. 深入windows的关机消息截获-从XP到Win7的变化(在XP中程序可以阻止关机,但是在Win7中程序无法阻止关机,可Block的时间从1秒调到了5秒) good

    之前写了一个软件用于实验室的打卡提醒,其中一个重要的功能是在关机之前提醒当天晚上是否已经打卡.之前我是在WM_ENDSESSION中弹出一个模态对话框来提醒,在XP中基本工作正常,在Win7中大多数时 ...

  4. 深入windows的关机消息截获-从XP到Win7的变化

    之前写了一个软件用于实验室的打卡提醒,其中一个重要的功能是在关机之前提醒当天晚上是否已经打卡.之前我是在WM_ENDSESSION中弹出一个模态对话框来提醒,在XP中基本工作正常,在Win7中大多数时 ...

  5. Windows 7下阻止系统关机

    从Vista开始,想阻止系统关机就开始变麻烦了,不能只拦截WM_QUERYENDSESSION了,操作系统只给一个应用程序两秒钟的时间去保存自己的东西,两秒钟之后,不管做完了没有,Game Over! ...

  6. 编程实现Windows关机、重启、注销

    要想编程使Windows关机.重启或者注销,可以使用ExWindowsEx这个API函数,该函数只有两个参数,第一个表示关机动作的标志,也就是你要让该函数关机呢,还是重启,还是注销等.可以使用EWX_ ...

  7. 再谈Delphi关机消息拦截 -- 之控制台程序 SetConsoleCtrlHandler(控制台使用回调函数拦截,比较有意思)

    这里补充一下第一篇文章中提到的拦截关机消息 Delphi消息拦截:http://blog.csdn.net/cwpoint/archive/2011/04/05/6302314.aspx 下面我再介绍 ...

  8. C/C++控制Windows关机/注销/重启的正确姿势

    简介 说到代码控制Windows关机/注销/重启的方式,有很多种,最简单的不过就是控制命令行,使用system("pause")函数执行一个shutdown -s -t 0,关机就 ...

  9. Ubuntu 拦截并监听 power button 的关机消息

    system:ubuntu 18.04 platform:rockchip 3399 board:NanoPi M4 前言 物理上的电源按键短按之后,系统直接硬关机了,导致应用程序无法保护现场,就直接 ...

随机推荐

  1. CentOS7搭建时间服务器-chrony(不坑)

    标签(linux): chrony 笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 之前centos6我们一直用的ntp时间服务器,虽然到CentOS7上也可以装 ...

  2. ng机器学习视频笔记(十六) ——从图像处理谈机器学习项目流程

    ng机器学习视频笔记(十六) --从图像处理谈机器学习项目流程 (转载请附上本文链接--linhxx) 一.概述 这里简单讨论图像处理的机器学习过程,主要讨论的是机器学习的项目流程.采用的业务示例是O ...

  3. oracle学习(一)

    作为一个入门选手,怕忘记,所以所有东西都尽量写下来.(省略oracle11g的安装过程) 一.sqlpuls用sys账户登录 (sqlplus是客户端连上服务器的一个工具) 1.使用cmd控制台登录 ...

  4. 排序算法之low B三人组

    排序low B三人组 列表排序:将无序列表变成有充列表 应用场景:各种榜单,各种表格,给二分法排序使用,给其他算法使用 输入无序列表,输出有序列表(升序或降序) 排序low B三人组 1. 冒泡排序 ...

  5. 给php加速安装APC

    说明:APC-3.1.13 适应于 php-5.4.27 下载: wget http://blog.xinfilm.com/softdir/APC-3.1.13.tgz tar -zxvf APC-3 ...

  6. java异常丢失及异常链

    1.Java中异常丢失的情况: 先定义三个异常: public class ExceptionA extends Exception { public ExceptionA(String str) { ...

  7. POJ 2079 Triangle [旋转卡壳]

    Triangle Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 9525   Accepted: 2845 Descript ...

  8. SDN第四次作业

    作业链接 1.阅读 了解SDN控制器的发展 http://www.sdnlab.com/13306.html http://www.docin.com/p-1536626509.html 了解ryu控 ...

  9. 痞子衡随笔:常用的数据传输差错检测技术(1)- 奇偶校验(Parity Check)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式数据传输里的差错检测技术-奇偶校验. 在嵌入式应用里,除了最核心的数据处理外,我们还会经常和数据传输打交道.数据传输需要硬件传输接口 ...

  10. Python编程软件的安装与使用——Windows、Linux和Mac

    Python版本:3.6.2  操作系统:Windows  作者:SmallWZQ 最近,有读者透露:Python软件如何安装?为什么自己安装的软件会有各种"奇怪"的问题?据此,本 ...