如何模拟Windows关机以进行调试?

时间:2009-02-06 16:11:42

标签: c# .net winforms shutdown

当Windows关闭时我的应用程序出现问题 - 我的应用程序没有很好地退出,导致显示“结束任务”窗口。如何使用调试器查看发生了什么?

有没有办法将Windows关闭消息发送到我的应用程序,因此它认为Windows正在关闭,所以我可以确切地看到它的行为方式?

5 个答案:

答案 0 :(得分:57)

Microsoft的Logo Testing Tools for 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认证测试用例文档,

  

重启管理器关闭消息是:

     

一个。带有LPARAM = ENDSESSION_CLOSEAPP(0x1)的WM_QUERYENDSESSION:GUI应用程序必须立即响应(TRUE)以准备重新启动。

     

湾带有LPARAM的WM_ENDSESSION = ENDSESSION_CLOSEAPP(0x1):应用程序必须在5秒内关闭(服务为20秒)。

     

℃。 CTRL_SHUTDOWN_EVENT:控制台应用程序必须立即关闭。

答案 1 :(得分:7)

我相信当Windows关闭时,它会向所有应用程序发送“WM_QueryEndSession”。要模拟Windows关闭,您可以创建一个小应用程序,只需将PostMessage与此消息一起发送到您的应用程序,然后查看会发生什么。 Windows可能会发送比实际关闭应用程序更多的消息(如WM_CLOSE),但只要您的应用程序收到“WM_QueryEndSession”消息,就意味着您的应用程序即将从其下面取出地毯。

答案 2 :(得分:1)

这可以使用 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 枚举。

相关链接:

答案 3 :(得分:0)

您可以使用SystemEvents.SessionEnding事件,该事件在用户注销或关闭时触发。使用它时要小心,但不保证有些资源可用。例如,我的应用程序需要在关闭时关闭服务器以使用户输出时钟(时钟应用程序),但是当发生此事件时,网卡有时已被禁用。由于你只是在进行清理,所以这应该可以正常工作。

答案 4 :(得分:0)

SendMessage可用于将带有任何参数的窗口消息发送到窗口。

  

对调试和测试非常有用。

  1. 使用WM_QUERYENDSESSION = LPARAM发送消息ENDSESSION_CLOSEAPP。 应用程序必须返回1(TRUE)以表示它已准备好关闭并重新启动。

  2. 使用LPARAM = WM_ENDSESSION发送消息ENDSESSION_CLOSEAPP 应用程序必须在指定的超时期限内关闭。