c# -.NET 1.1中未处理的异常处理程序

Translate

我正在维护.NET 1.1应用程序,因此我要承担的任务之一就是确保用户不会看到任何不友好的错误通知。

我添加了处理程序Application.ThreadExceptionAppDomain.CurrentDomain.UnhandledException,确实会被调用。我的问题是标准CLR错误对话框仍然显示(在调用异常处理程序之前)。

杰夫在博客上谈到了这个问题这里这里。但是没有解决方案。那么.NET 1.1中处理未捕获的异常并显示友好对话框的标准方法是什么?

Jeff的回答被标记为正确答案,因为他提供的链接包含有关如何执行所需操作的最完整信息。

This question and all comments follow the "Attribution Required."

所有的回答

Translate

哦,在Windows窗体中,您绝对应该能够使它工作。您唯一需要注意的是事情发生在不同的线程上。

我在这里有一篇旧的Code Project文章,该文章应该会有所帮助:

用户友好的异常处理

来源
Translate

AppDomain.UnhandledException是一个事件,而不是全局异常处理程序。这意味着,当它被提出时,您的应用程序已经不堪重负了,除了进行清理和错误日志记录之外,您无能为力。

幕后发生的事情是:框架检测到异常,将调用堆栈移到最顶端,没有找到可以从错误中恢复的处理程序,因此无法确定继续执行是否安全。因此,它启动了关闭序列,并出于对您的礼貌触发了此事件,以便您可以对已经结束的过程表示敬意。当在主线程中未处理异常时,会发生这种情况。

对于这种错误,没有单点解决方案。您需要在发生此错误的所有位置的上游放置一个真正的异常处理程序(捕获块),然后将其转发到(例如)全局处理程序方法/类,该方法/类将根据以下情况确定是否可以安全地进行报告和继续操作:异常类型和/或内容。

编辑:可以禁用(= hack)Windows内置的错误报告机制,因此当您的应用程序关闭时,不会显示强制性的“崩溃和刻录”对话框。但是,这对于所有系统中的应用程序,而不仅仅是您自己的应用程序。

来源
Translate

.NET 1.x Windows窗体应用程序中未处理的异常行为取决于:

  • 引发异常的线程类型
  • 是否在窗口消息处理期间发生
  • 是否将调试器附加到进程
  • DbgJitDebugLaunchSetting注册表设置
  • App.Config中的jitDebugging标志
  • 是否覆盖Windows Forms异常处理程序
  • 是否处理CLR的异常事件
  • 月相

未处理异常的默认行为是:

  • 如果在泵送窗口消息时在主线程上发生异常,则Windows窗体异常处理程序将拦截该异常。
  • 如果在泵送窗口消息时在主线程上发生异常,除非Windows窗体异常处理程序将其拦截,否则它将终止应用程序进程。
  • 如果该异常发生在手动,线程池或终结器线程上,则CLR会将其吞噬。

未处理的异常的联系点是:

  • Windows窗体异常处理程序。
  • JIT调试注册表开关DbgJitDebugLaunchSetting。
  • CLR未处理的异常事件。

Windows窗体内置的异常处理默认情况下执行以下操作:

  • Catches an unhandled exception when:
    • 异常在主线程上,没有附加调试器。
    • 窗口消息处理期间发生异常。
    • App.Config中的jitDebugging = false。
  • 向用户显示对话框并阻止应用终止。

您可以通过在App.Config中设置jitDebugging = true来禁用后一种行为。但是请记住,这可能是您终止应用终止的最后机会。因此,捕获未处理的异常的下一步是为事件Application.ThreadException注册,例如:

Application.ThreadException += new
Threading.ThreadExceptionHandler(CatchFormsExceptions);

请注意HKEY_LOCAL_MACHINE \ Software.NetFramework下的注册表设置DbgJitDebugLaunchSetting。这是我知道的三个值之一:

  • 0:显示询问“调试或终止”的用户对话框。
  • 1:让CLR处理异常。
  • 2:启动在DbgManagedDebugger注册表项中指定的调试器。

在Visual Studio中,转到菜单工具类选件调试准时制将此键设置为0或2。但是,在最终用户的计算机上,最好将值设置为1。请注意,此注册表项在CLR未处理的异常事件之前起作用。

最后一个事件是您记录未处理的异常的最后机会。它在您的Final代码块执行之前触发。您可以按以下方式拦截此事件:

AppDomain.CurrentDomain.UnhandledException += new
System.UnhandledExceptionEventHandler(CatchClrExceptions);
来源
Translate

这是控制台应用程序还是Windows Forms应用程序?遗憾的是,如果它是.NET 1.1控制台应用程序,则由MSFT开发人员在您引用的第二篇博客文章:

顺便说一句,在我的1.1机器上,来自MSDN的示例确实具有预期的输出。只是直到连接调试器(或没有)后,第二行才会显示。在v2中,我们进行了一些调整,以便在调试器附加之前触发UnhandledException事件,这似乎是大多数人期望的。

听起来.NET 2.0做得更好(谢谢),但是说实话,我从来没有时间回过头来检查。

来源
Ray
Translate

这是Windows窗体应用程序。被Application.ThreadException捕获的异常工作正常,并且我没有收到难看的.NET异常框(OK终止,取消调试?谁想到的??)。

我遇到了一些未被该异常捕获的异常,并最终导致了引起问题的AppDomain.UnhandledException事件。我认为我已经捕获了大多数此类异常,并且现在正在我们的漂亮错误框中显示它们。

因此,我只希望没有其他情况会导致Application.ThreadException处理程序无法捕获异常。

来源