【问题标题】:Intercepting WM_ENDSESSION message拦截 WM_ENDSESSION 消息
【发布时间】:2016-02-05 18:24:14
【问题描述】:

是否可以截取 WM_ENDSESSION 消息以防止其他应用程序接收到它?

我想命令该应用程序在 Windows 重新启动或关闭之前执行附加操作,并且无法以这种方式配置应用程序。

该应用程序是屏幕录像软件,它只是在 Windows 关闭时丢弃视频。我需要防止这种情况并保存视频。

【问题讨论】:

  • 您不必阻止 WM_ENDSESSION 以防您需要执行清理。您只需注册一个原因字符串。这在Application Shutdown Changes in Windows Vista 下进行了解释。
  • @IInspector:如果阻止应用程序更新为执行您所说的操作,它会告诉 Windows 不允许立即关闭(但用户仍然可以覆盖它并强制关闭)。两个应用程序都不会被通知用户试图在关机被阻止时关闭(除非用户强制它),因此阻止应用程序将无法在允许之前通知其他应用程序保存视频关机继续。
  • @IInspectable:看 RemyLebeau 的评论,他是对的。
  • 好的,ffmpeg 正确处理该消息并保存视频。无需拦截。

标签: windows winapi system-shutdown


【解决方案1】:

是否可以拦截 WM_ENDSESSION 消息以防止其他应用程序接收到它?

技术上是的,使用来自SetWindowsHookEx() 的消息挂钩。根据使用的钩子,您有时可以修改(而不是丢弃)消息,使其看起来像另一条消息,例如WM_NULL。然而,在WM_ENDSESSION 的情况下,它只是一个通知,而不是一个请求,所以无论应用程序对该消息做什么,Windows 仍然会继续关闭。

我想命令该应用程序在 Windows 重新启动或关闭之前执行附加操作,并且无法以这种方式配置应用程序。

该应用程序是屏幕录像软件,它只是在 Windows 关闭时丢弃视频。我需要防止这种情况并保存视频。

因此,您实际上并不想避免WM_ENDSESSION,您只是想延迟其他应用程序处理它,直到您首先执行操作之后。

最好的选择是简单地联系录像机作者并请求添加一项功能以在系统关闭时保存视频。

除此之外,MSDN 还说:

Application Shutdown Changes in Windows Vista

默认情况下,没有任何可见顶级窗口的应用程序将有 5 秒的时间来处理 WM_ENDSESSION,然后才会终止。

如果您的应用程序可能需要超过 5 秒的时间来完成其关闭处理以响应 WM_ENDSESSION,它应在其 WM_QUERYENDSESSION 处理程序中调用 ShutdownBlockReasonCreate(),并立即对 WM_QUERYENDSESSION 响应 TRUE,以免阻塞关闭。然后它应该在其 WM_ENDSESSION 处理程序中执行所有关闭处理。

这样,Windows 会将您的应用程序视为具有可见的顶级窗口,并给它 30 秒的时间来处理 WM_ENDSESSION。

因此,您可以尝试使用消息挂钩来拦截WM_QUERYENDSESSION 并让它调用ShutdownBlockReasonCreate() 并立即返回,然后拦截WM_ENDSESSION 以调用视频保存操作并在完成后调用ShutdownBlockReasonDestroy()。当然,假设录像机正在丢弃视频以回复 WM_ENDSESSION 而不是 WM_QUERYENDSESSION

有关 Windows 如何处理这两条消息的详细信息,请参阅 MSDN:

Shutdown Changes for Windows Vista

【讨论】:

  • 我应该在我的进程中执行还是将代码注入到记录器的进程中?
  • 您的应用程序可以调用SetWindowsHookEx() 来安装消息挂钩,但挂钩本身需要在DLL 中实现,以便可以注入到记录器的进程中。如果钩子方法不起作用,您可能必须实际将一些代码注入记录器进程(请参阅CreateRemoteThread() 和相关函数),并让该代码直接子类化记录器的窗口以拦截消息。
猜你喜欢
  • 2022-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
  • 2012-03-17
  • 2013-04-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多