用休眠代替关机
Tl;dr:是否可以在处理系统关闭消息之前捕获它们(并更改/删除它们)?
初步
我正在开发一个集群管理软件。目前,集群中的空闲机器正在被第三方软件关闭。在我的软件测试环境中,在关闭、启动和启动所有程序上浪费大量时间是不可接受的。因此,机器被视为空闲的时间点被设置为大约 3 小时。这并不是真正的“节能”。
这个想法是用休眠消息替换系统关闭消息。 操作系统是 Windows XP,但计划更新到 Windows 7。因此,理想情况下,该解决方案应该对两者都有效。
到目前为止的想法
替换
shutdown.exe
我在 UNIX 客户端上就是这样做的。但是,我不认为常见的 Windows 应用程序只是调用shutdown.exe
上的exec()
来关闭系统。相反,他们可能会调用ExitWindowsEx()
。我也想捕获此调用产生的消息。处理
WM_QUERYENDSESSION
这也不是一个解决方案,原因有两个:- 此消息以不可预测的顺序传递给所有正在运行的程序。即使我通过返回
FALSE
取消关闭,某些程序可能会更早收到消息并已经退出。 - 自 Vista 起,返回
FALSE
不会导致静默取消关闭。相反,整个屏幕都会被阻止,并通知用户阻止关闭的程序。因此,即使我此时设法进入休眠状态,下次启动时整个屏幕都会被阻止。
尤其是第一点至关重要。如果不花费宝贵的时间,我只能证明关闭机器是合理的。从休眠状态返回时不必重新启动程序是其中的一个重要部分。
- 此消息以不可预测的顺序传递给所有正在运行的程序。即使我通过返回
SetWindowsHookEx()
我想到了钩子。然而,这种方法似乎相当痛苦,因为这个MSDN文章指出,我必须以两种风格(x86_64 和 x86)交付我的程序和包含钩子的 DLL。这注定会失败。
但是假设我设法让它工作,在将系统的关闭消息分派到其他窗口之前,我似乎无法捕获系统的关闭消息,更不用说更改或删除该消息了。
限制
基本上没有限制。由于那些机器上运行的 Windows 是我自己安装的,所以一切顺利。如果手工制作的鼠标驱动程序(模拟鼠标移动以单击“好的,不要关闭”按钮)是解决方案,那么就这样吧(另一个指标,我不想这样做邪恶的 ;) )。解决方案越通用(例如能够拦截和更改任何消息)就越好!
任何提示和链接(未经测试的、实验性的东西)都值得赞赏。
Tl;dr: Is it possible to catch system shutdown messages (and alter/remove them) before they are being processed?
Preliminary
I am working on a cluster management software. Right now, idle machines in the cluster are being shut down by a third party software. In the environment my software is tested with, it is not acceptable to lose a lot of time on shutting down, booting up and starting all the programs. As a result, the point at which a machine is considered to be idle has been set to something like 3 hours. This is not really "power saving".
The idea is to replace the systems shutdown message with a hibernate message.
The OS is Windows XP but an update to Windows 7 is planned. So ideally, the solution should work on both.
Ideas so far
Replace
shutdown.exe
This is how I did it with the UNIX clients. However, I don't think that common Windows applications just callsexec()
onshutdown.exe
to get the system to shut down. Instead, they probably callExitWindowsEx()
. I want to catch the messages resulting from this call as well.Handling
WM_QUERYENDSESSION
This is not a solution, either, for two reasons:- This message is delivered to all running programs in an unpredictable order. Even if I cancel the shutdown by returning
FALSE
, some programs might have gotten the message earlier and exited already. - Since Vista, returning
FALSE
does not result in a silent cancellation of the shutdown. Instead, the whole screen is blocked and the user is informed about the program(s) blocking the shutdown. So even if I manage to go into hibernate at this point, at the next startup the whole screen is blocked.
Especially the first point is crucial. I can only justify shutting down the machines if it doesn't cost precious time. Not having to restart the programs when returning from hibernate is a big part of that.
- This message is delivered to all running programs in an unpredictable order. Even if I cancel the shutdown by returning
SetWindowsHookEx()
I thought about hooks. However, this method seems quite painful, since this MSDN article states, that I would have to deliver both my program and the DLL containing the hook in both flavors (x86_64 and x86). This is bound to fail.
But let's assume I manage to get this to work, I cannot seem to catch the system's shutdown message before it's being dispatched to other windows, let alone alter or delete that message.
Restrictions
There are basically no restrictions. Since the Windows running on those machine is being installed by myself, anything goes. If a hand-crafted mouse driver, which simulates mouse movement to click the "Ok, don't shutdown" button is the solution, so be it (another indicator, that I'm not trying to do evil ;) ). The more general the solution (e.g. being able to intercept and alter any message), the better!
Any hints and links (untested, experimental stuff) are appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
以下是防止关闭所需执行的步骤
编写一个 DLL 来捕获并重定向 ExitWindowsEx() 函数。您可以使用 Microsoft Detours 库 来完成此操作。在测试进程中测试此 dll。
测试完 DLL 后,默认情况下使用 AppInit_Dlls 注册表值或使用 detours 包提供的实用程序有选择地将 DLL 加载到您想要的任何进程中。
编写一个进程,使用其中一种 IPC 机制与您在所有进程中加载的 DLL 进行通信,以允许/拒绝/重定向关闭。
Here are the steps you need to do to prevent the shutdown
Write a DLL that captures and redirects the ExitWindowsEx() function. You can accomplish this using Microsoft Detours Library. Test this dll in your test process.
Once you have tested your dll, have that DLL load into every process by default using AppInit_Dlls registry value or use the utilities provided by detours package to selectively load the DLL into any process you want.
Write a process that uses one of the IPC mechanism to communicate with your DLL loaded in all the process to allow/deny/redirect the shutdown.