【问题标题】:How to catch ALL exceptions/crashes in a .NET app [duplicate]如何在 .NET 应用程序中捕获所有异常/崩溃 [重复]
【发布时间】:2010-09-10 02:17:51
【问题描述】:

可能重复:
.NET - What’s the best way to implement a “catch all exceptions handler”

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

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

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

.NET 世界中的等价物是什么,以便我可以处理/记录/静默所有可能的错误情况?

【问题讨论】:

  • 请记住,有many ways for a process to "crash",每个都可能需要特殊的技巧来捕获 - 所有这些都是托管异常降低应用程序的方法之外的。最后一个复杂因素是,例如,WinForms 可能会通过在异常到达应用程序的全局异常处理程序之前捕获异常来干扰您的尝试。

标签: c# .net exception-handling


【解决方案1】:

您可以在 AppDomain.UnhandledException 事件中添加一个事件处理程序,当异常被抛出但未被捕获时会被调用。

【讨论】:

  • 设置 AppDomain.UnhandledException 似乎与调用 Win32 SetUnhandledExceptionFilter 完全一样。如果您的应用的另一部分安装了过滤器,AppDomain.UnhandledException 将正确“链接”并调用另一个过滤器。
【解决方案2】:

与其他人发布的内容相反,捕获所有异常并没有错。重要的是要妥善处理它们。如果您有堆栈溢出或内存不足的情况,应用程序应该为它们关闭。另外,请记住,OOM 条件可能会阻止您的异常处理程序正确运行。例如,如果您的异常处理程序显示一个带有异常消息的对话框,如果您的内存不足,则可能没有足够的空间用于对话框显示。最好记录下来并立即关闭。

正如其他人所提到的,您可以处理 UnhandledException 和 ThreadException 事件来收集可能会错过的异常。然后只需在主循环周围抛出一个异常处理程序(假设是一个 winforms 应用程序)。

此外,您应该知道 OutOfMemoryExceptions 并不总是因内存不足而引发。 OOM 条件可以在您的代码或框架中触发各种异常,这些异常不一定与真正的底层条件内存不足这一事实有关。当根本原因实际上是内存不足时,我经常看到 InvalidOperationException 或 ArgumentException。

【讨论】:

  • 我很惊讶没有更多的赞成票。 Juanma 在捕捉事件方面做了一个很好的补充,然而,这并没有涵盖所有场景。应该从中得到的信息是,有时打破标准是可以的。使用显式功能捕获特定的异常类型,并使用包装器来捕获和处理其他任何内容。如果您正在编写 DLL,根据我的经验,您应该有一个从异常继承的类,创建您的功能,将未处理的异常包装在属性 InnerException 中并抛出。
【解决方案3】:

This article in codeproject by our host Jeff Atwood 是您所需要的。 包括用于捕获未处理异常的代码以及向用户显示有关崩溃信息的最佳实践。

【讨论】:

    【解决方案4】:

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

    protected void Application_Error(Object sender, EventArgs e)
    

    方法

    【讨论】:

    • 注意:此答案适用于 ASP.NET 应用程序而非控制台应用程序。
    【解决方案5】:

    请注意,某些异常很难捕获 - 或者大多数情况下无法捕获,

    • OutOfMemoryException:您在 catch 处理程序中执行的任何操作都可能分配内存(在 CLR 的托管或非托管端)并因此触发另一个 OOM
    • StackOverflowException:取决于 CLR 是否足够早地检测到它,您可能会收到通知。最坏的情况是,它只会终止进程。

    【讨论】:

      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

        虽然在没有计划正确处理它们的情况下捕获所有异常肯定是一种不好的做法,但我认为应用程序应该以某种优雅的方式失败。崩溃不应该把用户吓死,至少它应该显示错误的描述,向技术支持人员报告的一些信息,理想情况下是一个关闭应用程序并重新启动它的按钮。在理想情况下,应用程序应该能够将用户数据转储到磁盘上,然后尝试恢复它(但我发现这要求太多了)。

        反正我通常用:

        AppDomain.CurrentDomain.UnhandledException
        

        【讨论】:

          【解决方案8】:

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

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

          【讨论】:

            【解决方案9】:

            我认为您甚至不应该捕获所有异常,而是最好将它们显示给用户。这样做的原因是您应该只捕获您可以实际处理的异常。如果您遇到一些导致程序停止但仍然捕获它的异常,这可能会导致更严重的问题。 另请阅读FAQ: Why does FxCop warn against catch(Exception)?。

            【讨论】:

            • 是的,但如果能够在应用程序完全死机之前记录所有信息(堆栈跟踪、所有依赖项的版本、可能是屏幕截图),那就太好了……
            【解决方案10】:

            请注意,捕获这些未处理的异常可能会改变应用程序的安全要求。您的应用程序可能会在某些情况下停止正常运行(从网络共享等运行时)。请务必彻底测试。

            【讨论】:

              【解决方案11】:

              同时使用两者并没有什么坏处 AppDomain.CurrentDomain.UnhandledException Application.ThreadException

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

              【讨论】:

              • 来自 MSDN:如果在默认应用程序域中处理了 UnhandledException 事件,那么无论线程在哪个应用程序域中启动,任何线程中的任何未处理异常都会在此处引发。(因此在某些情况下可能不会处理所有的应用程序域,但肯定会处理同一个应用程序域中的线程......当然,那些捕获的异常仍然可能终止应用程序。)
              • @ebyrob:信任 MSDN,但要验证 ;)
              • 我刚刚验证我可以使用 UnhandledException 事件捕获 Timer 和 ThreadPool 异常。 (虽然两者都导致了一个死应用)
              • @ebyrob:非常好。它在 .NET 1.1、2.0...4.0 中是否同样有效?请注意,此答案已有 3.5 年历史,因此很可能是指 .net 2.0
              • 最新补丁级别在 2.0 和 4.0 中似乎相同。从您链接的文章中:“这些线程只是死了,没有捕获未处理的异常事件,没有向用户发出警告,什么都没有。” (这似乎不是真的,至少在正常情况下,并且假设没有相关的修补程序。)
              猜你喜欢
              • 1970-01-01
              • 2014-11-29
              • 2013-09-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-06-13
              • 2017-07-04
              相关资源
              最近更新 更多