如何模拟 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 上运行颤振。在我的调试模式下进行了调整。如何解决颤振医生命令的问题

如何用cmd打开Tornado Vxsim进行仿真调试

Window系统上自制快速关机脚本

c# 如何截获windows关机或注销消息

Xamarin.iOS:捆绑笔尖没有被复制到模拟器/设备以进行调试/发布

如何删除诸如“等待调试器连接...调试器已连接调试器连接丢失”之类的错误。关机……”