Windows——利用WM_QUERYENDSESSION实现电脑直接关机时对应用程序进行某些处理

作者:小 琛
欢迎转载,请标明出处

需求场景

应用在每次退出时,都需要做某些检测操作,例如:版本号、资源信息。但针对某个极端情况,应用未退出,使用者直接将电脑进行了关闭,从而我的应用数据出现了错误

计算器关机时针对未关闭应用的处理方式

  • 在Windows操作系统中,当用户关闭计算机或注销用户时,操作系统会向所有运行的进程发送关闭信号。这个信号告知进程系统即将关闭,通常是通过发送WM_CLOSE消息(GUI应用程序)或CTRL_SHUTDOWN_EVENT事件(控制台应用程序)来实现的。这些消息和事件会触发应用程序执行关闭操作,包括清理和保存数据等。
  • 如果应用程序在接收到关闭信号后没有正确地执行关闭操作,并且系统超时时间到达,则操作系统可能会直接调用TerminateProcess函数来强制终止应用程序。这种情况下,应用程序将会被直接终止,而不会有机会进行正常的关闭和清理操作。

总结:操作系统会先发送WM_CLOSE消息,目的是让应用自行完结。若超时进程仍未退出,则会使用TerminateProcess直接进行退出

WM_QUERYENDSESSION

WM_QUERYENDSESSION 是一个Windows消息,用于向应用程序发送一个询问消息,询问应用程序是否愿意响应系统关闭或注销事件。当系统要关闭或注销时,操作系统会发送WM_QUERYENDSESSION消息给所有正在运行的应用程序,以询问它们是否愿意响应并执行一些清理操作。

思路

  • 应用程序可以通过处理WM_QUERYENDSESSION消息来决定是否终止当前会话。如果应用程序返回,表示它不愿意响应系统关闭或注销事件,系统会尝试终止应用程序,但不会等待应用程序保存数据或执行其他清理操作。如果应用程序返回非0(真),系统会等待应用程序完成必要的清理操作,然后再终止应用程序。
  • 例如在Qt中,可以通过重载nativeEvent函数来处理WM_QUERYENDSESSION消息。当收到这个消息时,执行一些需要在系统关闭前完成的操作,比如保存数据、关闭文件等。这样可以确保应用程序在系统关闭或注销时能够做一些额外的处理。

注意:这个过程要尽可能轻量

例子

class NativeEventFilter : public QObject, public QAbstractNativeEventFilter {
public:
	explicit NativeEventFilter(QObject* parent = 0) : QObject(parent) {}

	bool nativeEventFilter(const QByteArray& et, void* msg, long* result) Q_DECL_OVERRIDE {
		bool ret = false;
		if (et == "windows_generic_MSG" || et == "windows_dispatcher_MSG") {
			if (auto const pMsg = static_cast<MSG*>(msg); pMsg->message == WM_USER_WAKE) {
				wakePlayer();

				if (result) *result = true;
				ret = true;
			} else if (pMsg->message == WM_CLOSE) {
				// do something
		 	} else if (pMsg->message == WM_QUERYENDSESSION) {
				// do something
				if (result) *result = TRUE;	 // Indicate that the session can end
				ret = true;
			}
		}
		return ret;
	}
};

// 在进程初始化时
	NativeEventFilter __filter;
	installNativeEventFilter(&__filter);

在这个例子中,我自定义了一个事件处理类,里面实现了当接收到原生的Windows消息时,检查是否是WM_QUERYENDSESSION消息,并在接收到该消息时执行一些操作,设置result为非0表示愿意响应系统关闭或注销事件。

同时我在我的application初始化时,生成了一个对象,调用installNativeEventFilter注册一个自定义的事件过滤器对象。

这样就可以实现,在电脑关闭时,正常响应我需要的事件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值