杀死正在运行的程序的方法以及如何捕获它们?
Posted
技术标签:
【中文标题】杀死正在运行的程序的方法以及如何捕获它们?【英文标题】:Ways to kill a running program and how to trap them? 【发布时间】:2010-11-15 16:31:51 【问题描述】:我们有不同的方法来杀死正在运行的 C# 程序。
-
ctrl + C;
任务栏然后右键单击其图标,然后在弹出窗口中选择“关闭”;
任务管理器,选择其可执行名称,然后点击结束进程;
控制台窗口,使用kill命令;
也许更多。
我在这里要问的是如何在我的 C# 程序中处理它们以保证我的 C# 程序在可能的情况下优雅地退出。我知道如何捕获 ctrl + C,但其他人不知道。你能帮助我吗?谢谢,
【问题讨论】:
为什么?你想做什么? “保证我的 C# 程序正常退出”你做不到。 什么技术? WinForms、控制台、WPF? Capture console exit C# 的可能重复项 用户经常试图“杀死”一个进程,因为它没有响应和/或行为不端。在这种情况下,操作系统比对进程更尊重用户,并且可能没有礼貌地通知它即将死亡。这是正确的做法。 【参考方案1】:在退出时运行代码的最佳保证是 finally 语句。
请注意,当您使用此机制时,您的程序必须在 try
块中运行。
我相信finally
中的块唯一没有被执行的时间是:
一个***Exception
;
Corrupted state exceptions(来自 .NET 4);
通过任务管理器强制终止(非托管进程终止);
整个系统崩溃(例如拔掉电源线)。
See Keep Your Code Running with the Reliability Features of the .NET Framework 进行深入分析。
【讨论】:
使用 .NET 4 运行时finally
块也会因损坏状态异常而被跳过。
@Brian Rasmussen - 非常感谢;添加到答案中。
您错过的一个主要情况是 finally 块中的代码是否抛出了自己的异常。这尤其糟糕,因为您不仅在抛出异常后不执行任何语句,而且实际上掩盖了从 try/catch 部分抛出的任何异常,因为运行时现在必须在返回展开之前处理这个新异常旧的。
@KeithS - 这是正确的,但是,finally
块已经运行(直到那时),并且堆栈更高的任何其他 finally
块都会运行,对吧?我觉得这属于“你有机会”的类别:)。【参考方案2】:
场景 2 基本上调用 Application.Exit(),这相当于正常关闭与您的进程相关的所有线程。它还会触发可用于执行任何其他清理的事件。
可以通过将处理程序附加到 WinForms 应用程序的 Application.ThreadException 事件来“捕获”3 和 4。当将要从程序中抛出任何异常以由运行时处理时会触发此事件(这将终止程序集的执行并清理沙箱)。但是,此时除了向事件日志写入一些内容或清理任何静态数据(如 IoC 容器或存储库)之外,您几乎不需要做任何事情,即使这样也是有问题的,因为如果其中一个对象导致异常,您可以很容易地在尝试处理最后一个异常时抛出另一个异常。
基本上,如果您的用户正在使用“kill”或“End Process”来关闭您的应用程序,则存在非常错误的情况,您可能应该先解决用户这样做的根本原因,然后再尝试优雅地捕获此类终止行为。
【讨论】:
【参考方案3】:不能陷阱。你无法避免杀死一个程序。但你总是可以订阅杀死。想象一下当人们拔掉电源插头时你是如何被困的......
.NET 2.0
订阅AppDomain.CurrentDomain.ProcessExit事件
.NET 3.5
Application.Exit 事件
有用的链接
AppDomain.CurrentDomain.ProcessExit and cleanup
How to detect when application terminates?
How to detect when main thread terminates?
【讨论】:
还有AppDomain.CurrentDomain.UnhandledException以上是关于杀死正在运行的程序的方法以及如何捕获它们?的主要内容,如果未能解决你的问题,请参考以下文章