如何模拟 Windows 关机以进行调试?
Posted
技术标签:
【中文标题】如何模拟 Windows 关机以进行调试?【英文标题】:How to simulate Windows shutdown for debugging? 【发布时间】:2010-10-05 23:24:09 【问题描述】:Windows 关闭时我的应用程序出现问题 - 我的应用程序无法正常退出,导致显示“结束任务”窗口。如何使用调试器查看发生了什么?
有没有办法将 Windows 关闭消息发送到我的应用程序,以便它认为 Windows 正在关闭,以便我可以确切地看到它的行为?
【问题讨论】:
【参考方案1】:Microsoft 的 Windows 徽标测试工具中有一个名为 Restart Manager (rmtool.exe) 的工具,可用于向进程发送关闭和重新启动消息。标志测试工具可以在这里下载:
http://download.microsoft.com/download/d/2/5/d2522ce4-a441-459d-8302-be8f3321823c/LogoToolsv1.0.msi
然后你可以为你的进程模拟关闭:
rmtool.exe -p [PID] -S
其中 [PID] 是进程 ID。根据 Vista Logo 认证测试用例文档,
重新启动管理器关闭消息是:
一个。 WM_QUERYENDSESSION with LPARAM = ENDSESSION_CLOSEAPP(0x1):GUI 应用程序必须立即响应 (TRUE) 以准备重新启动。
b. WM_ENDSESSION with LPARAM = ENDSESSION_CLOSEAPP(0x1):应用程序必须在 5 秒内关闭(服务为 20 秒)。
c。 CTRL_SHUTDOWN_EVENT:控制台应用程序必须立即关闭。
【讨论】:
太棒了! (我还没有尝试过 - 如果有人使用它并且可以提供反馈,那就太好了) 您的链接已损坏。徽标测试工具是旧的 Windows 7 客户端软件徽标计划的一部分。这些工具不再出现在 Microsoft 的网站上。这些工具似乎已被 Windows 应用程序认证工具包所取代,它是 Windows 10 桌面应用程序认证计划的一部分。该套件不包括rmtool.exe
,仅包括rmlogotest.exe
。我在其他地方写过一些关于rmlogotest.exe
的文章;要阅读我写的内容,请关注this link。
rmlogotest.exe
确实向您的应用程序发送了一些消息,我怀疑它们与 rmtool.exe
过去发送的消息相同,但我尚未确定。
链接返回404错误,表示文件不存在。
打开链接可以使用Wayback Machine网站:web.archive.org/web/20070403002537/http://…【参考方案2】:
我相信当 Windows 关闭时,它会向所有应用程序发送“WM_QueryEndSession”。要模拟 Windows 关闭,您可以创建一个小应用程序,该应用程序只将此消息发送到您的应用程序的 PostMessage,然后查看会发生什么。 Windows 可能会发送比实际关闭您的应用程序更多的消息(如 WM_CLOSE),但每当您的应用程序收到“WM_QueryEndSession”消息时,这意味着您的应用程序即将从它下面拉出地毯。
【讨论】:
此外,WM_QueryEndSession 之后是 WM_EndSession(假设收到它的应用程序全部OK)。 非常好 - 感谢 JMD 的澄清。我认为必须有一条额外的消息,但我不确定它是什么。 我可以使用任何有用的工具来发送此类消息而不是自己制作消息? 我不知道任何应用程序,但你可以这样做: [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool PostMessage(HandleRef hWnd , uint Msg, IntPtr wParam, IntPtr lParam);然后只需调用 PostMessage(handle, WM_whatever, IntPtr.Zero, IntPtr.Zero); 哦,要从应用程序外部获取窗口句柄,您可以使用 Visual Studio 附带的 Spy++,或免费提供且更易于使用的优秀“Winspector Spy”。【参考方案3】:SendMessage 可用于向窗口发送带有任何参数的窗口消息。
对于调试和测试非常有用。
使用LPARAM
= ENDSESSION_CLOSEAPP
发送消息WM_QUERYENDSESSION
。
应用程序必须返回 1 (TRUE) 以表明它已准备好关闭并重新启动。
使用 LPARAM = ENDSESSION_CLOSEAPP
发送消息 WM_ENDSESSION
应用程序必须在指定的超时期限内关闭。
【讨论】:
【参考方案4】:这可以使用rmlogotest.exe
工具来完成。见以下链接:
https://superuser.com/questions/959364/on-windows-how-can-i-gracefully-ask-a-running-program-to-terminate#1154058
如果你使用的是 WPF,那么你可以处理额外的事件:
Application.SessionEnding += Application_SessionEnding;
您可以在其中设置 e.Cancel = true;
以中止应用程序关闭。
我认为rmlogotest.exe
使用 5 秒的超时,然后它会告诉你
LOGO Validation FAILED
.
如果您在应用程序中放置某种消息框确认 - 您会失败,因为最终用户可能需要 5 秒以上的时间才能做出响应。
我猜从 windows 的角度来看,如果 5 秒过去了,它无论如何都想重新启动 - 如果最终用户没有保存他的文档/工作 - 那么 windows 可能希望将它复制到其他地方。
从我的角度(作为应用程序开发人员) - 失败是可以接受的
LOGO Validation FAILED
,用户可以自行决定——他是在 5 秒后终止我的应用程序并丢失他的文档,还是保存文档并手动关闭我的应用程序。
如果需要广播WM_QUERYENDSESSION
消息,则需要通过以下方式发送
SendMessage
到当前进程中的所有窗口。起始示例代码可以从这里找到:
https://github.com/qakit/headless.git
但它只发送WM_ENDSESSION
消息,您需要使用WM_QUERYENDSESSION
代替并添加给定进程的windows 枚举。
相关链接:
https://devblogs.microsoft.com/oldnewthing/20130627-00/?p=3973 https://devblogs.microsoft.com/oldnewthing/20170329-00/?p=95855【讨论】:
【参考方案5】:您可以使用SystemEvents.SessionEnding 事件,该事件在用户注销或关闭时触发。使用时要小心,但不能保证某些资源可用。例如,我的应用程序在关闭时需要访问服务器以将用户打卡(时钟应用程序),但是当此事件发生时,网卡有时已经被禁用。由于您只是在进行清理,因此应该可以正常工作。
【讨论】:
如何模拟关机来试试你写的东西?以上是关于如何模拟 Windows 关机以进行调试?的主要内容,如果未能解决你的问题,请参考以下文章
我想用我的 android 手机作为模拟器在 windows 7 上运行颤振。在我的调试模式下进行了调整。如何解决颤振医生命令的问题