任务管理器中的“结束任务”始终设置CloseReason.UserClosing

时间:2014-03-07 13:11:35

标签: winforms kill-process taskmanager

如果客户试图强制关闭应用程序,我想记录。我知道没有机会抓住进程杀死。但是应该可以通过主窗体关闭事件来了解'CloseReason.TaskManagerClosing'的原因。

但是我在Windows 8.1下做的任何测试我总是得到一个CloseReason.UserClosing原因。但在这种情况下(与普通的CloseReason.UserClosing相比)我运行用户代码大约0.2秒后我的程序被杀死了!

这是Windows 8.1中的新行为吗?

2 个答案:

答案 0 :(得分:8)

是的,我明白这一点。是的,这是一个Windows更改,以前版本的任务管理器直接向窗口发送WM_CLOSE通知。我现在看到它发出了与关闭按钮(WM_SYSCOMMAND,SC_CLOSE)关闭窗口时发出的完全相同的命令。或按Alt + F4或使用系统菜单。因此,Winforms不再能够区分任务管理器和关闭窗口的用户之间的差异,而是获得CloseReason.UserClosing。

接下来会发生什么,如果你没有足够快地响应关闭命令,那么任务管理器会使用TerminateProcess()立即暗杀您的程序。

请记住,当用户通过任务管理器中止程序时尝试保存数据是一种不好的做法。如果您的程序出现故障,您的用户通常会使用此功能,您无法再真正信任该数据,并且您可能会冒着写垃圾的风险。现在,您的保存代码被中止,部分写入的文件的高赔率或者不再可用的dbase数据更加复杂。

对此没有简单的解决方法,Windows将要修补以恢复旧行为的几率非常接近于零。以事务方式保存数据非常非常重要,因此如果保存代码中止,您不会销毁有价值的数据。使用File.Replace()获取文件数据,使用dbase事务进行dbase写入。

检测此情况的不完美方法是使用Form.Deactivate和Activate事件。如果您看到Deactivate事件并且FormClosing事件触发,那么另一个程序终止您的事件的合理几率。

但是你处理这个问题的正常方法是常见的,如果用户在没有保存数据的情况下结束程序,那么你会显示一个询问是否保存数据的对话框。任务管理器确保这不会比这更进一步。

答案 1 :(得分:0)

确定任务管理器何时关闭程序的另一种解决方案是通过检查主窗体或其任何控件是否具有焦点。当您通过任务管理器关闭时,该应用程序不会处于焦点状态,而如果您通过关闭按钮或Alt + F4进行关闭,则该应用程序确实具有焦点。我使用了一个简单的if检查:

private void MyForm_Closing(object sender, FormClosingEventArgs e)
{
    if (this.ContainsFocus)
    {
        // Put user close code here
    }
}