C#WinForms托盘应用程序 - 没有捕获Windows关闭事件

时间:2015-12-07 14:53:07

标签: c# .net windows winforms shutdown

我正在编写一个监控状态的程序。它启动主窗口(LoginForm)以询问用户凭据,然后隐藏表单。之后,LoginForm进入NotifyIcon并且所有剩余的工作都是在LoginForm隐藏的情况下完成的。我已经在LoginForm的FormClosing事件中实现了所有清理工作。在正常的退出过程中,一切都很完美。

问题是该程序一直处于托盘中,我倾向于忘记在关闭窗口之前将其退出 - 程序在关闭事件时不会保存状态。

我已经阅读了很多论坛和文档,而且从我读过的事件中,FormClosing / FormClosed + SessionEnding / SessionEnded必须解雇。但看起来他们似乎并没有开火。甚至不能在SessionEnding中取消关闭(愚蠢的e.Cancel = true) - 程序在没有到达的地方消失。

我自己做了一个小型调试库,将调试信息写入文件,并立即刷新缓存。我已经为所有事件添加了调试消息。当我尝试在Windows中注销用户(与关闭相同)进行测试时 - 我发现通常没有触发任何事件,只是程序消失了。没有例外我可以捕获,没有事件等。手动或通过" taskkill / IM" - 我看到了所有预期的调试打印输出。更有趣的是 - 有时程序会在Windows关闭期间达到关闭事件并进行适当的清理工作。

已经浪费了几天的时间。在MS文章中建议的Overriden WndProc - 程序也没有到达WndProc(以确保它在关闭表单之前首先出现)。尝试而不是FormClosing事件来覆盖LoginForm的OnClosing - 没有运气。添加了UnhandledException处理程序,Microsoft.Win32.SessionEnding,Microsoft.Win32.SessionEnded,Form.FormClosing,Form.FormClosed事件处理程序 - 没有运气。

我怀疑这是隐藏表单的问题,或者只是在关机期间发生某种异常(资源处理?)。我怎么才能找到为什么会这样?是否有一些简单的方法可以模拟单个应用程序的Windows关闭,以便在VS中进行调试?我已经尝试过RMTool - 由于某种原因,它无法模拟关机,程序只是忽略了它。

更新:程序使用System.Timers.Timer定期轮询服务器以进行任何更改。

2 个答案:

答案 0 :(得分:2)

我已经对此进行了一些研究,基本上,在Windows XP之后,他们改变了关闭处理的方式。

您无法使用form_closing事件等可靠地阻止或捕获关闭事件。

您必须使用新的API才能这样做。这里有一个完整的例子:http://bartdesmet.net/blogs/bart/archive/2006/10/25/Windows-Vista-2D00-ShutdownBlockReasonCreate-in-C_2300_.aspx

您应该可以调用该功能来阻止关闭(显示诸如“保存更改...”之类的消息),然后在后台保存并退出您的应用程序。程序退出后,应该允许Windows继续关闭。

答案 1 :(得分:0)

我认为Windows只是配置为自动关闭所有应用程序,因此应用程序没有机会捕获SessionEnding事件等等:查看http://www.addictivetips.com/windows-tips/disable-automatic-termination-of-applications-during-shutdown-in-windows-7/或检查计算机配置中的配置>管理模板>系统>关机选项。