如何捕捉.NET应用程序中的所有exception/崩溃

可能重复:
.NET – 什么是实现“捕获所有exception处理程序”的最佳方式

我有一个.NET控制台应用程序崩溃,并显示一条消息给用户。 我的所有代码都在try{<code>} catch(Exception e){<stuff>}块中,但偶尔还会显示错误。

在Win32应用程序中,您可以通过安装各种exception处理程序捕获所有可能的exception/崩溃:

 /* C++ exc handlers */ _set_se_translator SetUnhandledExceptionFilter _set_purecall_handler set_terminate set_unexpected _set_invalid_parameter_handler 

什么是在.NET世界相当于所以我可以处理/logging/安静所有可能的错误情况?

与其他人发布的内容相反,捕捉所有exception没有任何错误。 重要的是适当地处理它们。 如果你有堆栈溢出或内存不足的情况,应用程序应该closures它们。 另外,请记住,OOM条件可以防止exception处理程序正常运行。 例如,如果exception处理程序显示一个包含exception消息的对话框,如果内存不足,对话框显示可能没有足够的剩余空间。 最好logging下来并立即closures。

正如其他人提到的那样,您可以处理UnhandledException和ThreadException事件来收集可能会错过的exception。 然后简单地在你的主循环周围(假设一个winforms应用程序)抛出一个exception处理程序。

此外,你应该知道,OutOfMemoryExceptions并不总是抛出内存不足的条件。 一个OOM条件可能触发你的代码或框架中的各种exception,这些exception与真实的底层条件超出内存的事实并不一定有关系。 当底层原因实际上内存不足时,我经常看到InvalidOperationException或ArgumentException。

您可以将事件处理程序添加到AppDomain.UnhandledException事件中,并且在抛出exception并且未捕获时调用它。

我们的主持人Jeff Atwood的代码项目中的这篇文章就是您所需要的。 包含捕获未处理的exception和向用户显示有关崩溃信息的最佳实践的代码。

Global.asax类是你的最后一道防线。 看着:

 protected void Application_Error(Object sender, EventArgs e) 

方法

请注意,一些exception是很危险的,或者大部分是无法捕捉的,

  • OutOfMemoryException:在catch处理程序中执行的任何操作都可能会分配内存(在CLR的托pipe或非托pipe端),从而触发另一个OOM
  • StackOverflowException:根据CLR是否足够早地检测到它,您可能会收到通知。 最糟糕的情况,它只是杀死过程。

您可以使用AppDomain.CurrentDomain.UnhandledException来获取事件。

尽pipe捕捉所有的exception但没有妥善处理它们的计划肯定是一种不好的做法,但我认为应用程序应该以一种优雅的方式失败。 崩溃不应该吓到用户,至less它应该显示错误的描述,一些信息报告给技术支持的东西,最好是一个button来closures应用程序并重新启动它。 在理想的情况下,应用程序应该能够将磁盘上的用户数据转储,然后尝试恢复它(但是我看到这太多了)。

无论如何,我通常使用:

 AppDomain.CurrentDomain.UnhandledException 

您也可以使用Application.ThreadException事件。

一旦我开发在基于COM的应用程序中运行的.NET应用程序, 这个事件是非常有用的,因为AppDomain.CurrentDomain.UnhandledException在这种情况下不起作用。

我想你甚至不应该捕获所有exception,但最好让他们显示给用户。 这是因为你应该只捕获你可以处理的exception。 如果遇到一些导致程序停止但仍然捕获的Exception,这可能会导致更严重的问题。 另请阅读常见问题解答:为什么FxCop警告不要捕捉(例外)? 。

请注意,捕获这些未处理的exception可能会改变应用程序的安全需求。 在某些情况下,您的应用程序可能会停止正常运行(从networking共享等运行时)。 一定要彻底testing。

它不会伤害使用AppDomain.CurrentDomain.UnhandledException Application.ThreadException

但请记住,这些处理程序不会捕获次线程上的exception; 如果需要,可以使用SafeThread作为辅助线程