当 Windows 关闭时,我的应用程序出现问题 - 我的应用程序没有很好地退出,导致显示“结束任务”窗口。如何使用调试器查看发生了什么?
有没有办法将 Windows 关闭消息发送到我的应用程序,以便它认为 Windows 正在关闭,所以我可以确切地看到它的行为方式?
在微软的 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) 以准备重新启动。
湾。WM_ENDSESSION with LPARAM = ENDSESSION_CLOSEAPP(0x1):应用程序必须在 5 秒内关闭(服务为 20 秒)。
C。CTRL_SHUTDOWN_EVENT:控制台应用程序必须立即关闭。
我相信当 Windows 关闭时,它会向所有应用程序发送“WM_QueryEndSession”。要模拟 Windows 关闭,您可以创建一个小应用程序,该应用程序只将此消息发送到您的应用程序的 PostMessage,然后查看会发生什么。Windows 可能会发送比实际关闭您的应用程序更多的消息(如 WM_CLOSE),但是每当您的应用程序收到“WM_QueryEndSession”消息时,这意味着您的应用程序即将从它下面拉出地毯。
SendMessage可用于向窗口发送带有任何参数的窗口消息。
对于调试和测试非常有用。
WM_QUERYENDSESSION
使用LPARAM
=发送消息ENDSESSION_CLOSEAPP
。应用程序必须返回 1 (TRUE) 以指示它已准备好关闭并重新启动。
发送WM_ENDSESSION
带有 LPARAM =ENDSESSION_CLOSEAPP
应用程序必须在指定的超时期限内关闭的消息。
这可以使用rmlogotest.exe
工具来完成。请参阅以下链接:
如果您使用的是 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
并添加给定进程的窗口枚举。
相关链接:
您可以使用SystemEvents.SessionEnding事件,该事件在用户注销或关闭时触发。使用时要小心,但不能保证某些资源可用。例如,我的应用程序在关闭时需要访问服务器以将用户打卡(时钟应用程序),但是当此事件发生时,网卡有时已经被禁用。由于您只是在进行清理,因此应该可以正常工作。