目的:当用户注销系统的时候,注销前,让我的程序执行几行代码(释放资源/关闭端口之类的)。
思路:就跟把系统注销、重启和关机的消息都拦截下来,并销毁掉,不让其执行注销、重启和关机等操作原理是一样的。因为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重载。

其函数体如下:
LRESULT CLabRelayDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
// WM_QUERYENDSESSION消息是Windows向你询问Windows能否关闭
// WM_ENDSESSION消息表示提示你Windows即将关闭。
switch(message) {
case WM_ENDSESSION:
// 把消息销毁掉,不让其正确转发。
//message = WM_USERMESSAGE_NULL;
//turn off the relay
if(relayState==RELAY_ON)
turnOff();
break ;
case WM_QUERYENDSESSION: //注销/关机
//turn off the relay
if(relayState==RELAY_ON)
turnOff();
break ;
}
return CDialog::WindowProc(message, wParam, lParam);
}就这样,系统注销的时候我的函数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
非常有帮助的链接:
http://www.cnblogs.com/likebeta/archive/2012/03/31/2426632.html
http://blog.sina.com.cn/s/blog_7ce2cb410100wydw.html
http://www.cnblogs.com/lidabo/archive/2012/11/29/2795269.html
http://blog.csdn.net/silvervi/article/details/5131299
http://blog.csdn.net/goingup/article/details/457128