2008-08-04 85 views
22

我维护.NET 1.1应用程序,并且我负责的其中一件事是确保用户没有看到任何不友好的错误通知。.NET 1.1中的未处理的异常处理程序

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

Jeff在他的博客herehere上讨论了这个问题。但是没有解决办法。那么.NET 1.1中的标准方式是处理未捕获的异常并显示一个友好的对话框?

Jeff的回答被标记为正确答案,因为他提供的链接提供了关于如何完成所需内容的最完整信息。

回答

11

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

我有一个旧的代码项目的文章在这里,这应有助于:

User Friendly Exception Handling

3

这是控制台应用程序还是Windows窗体应用程序? - 如果它是一个.NET 1.1的控制台应用程序,这是可悲的是,在设计它是由在second blog post you referenced的MSFT dev的证实:

顺便说一句,我的1.1机器从MSDN的例子确实有预期的输出;只是第二行直到你连接了一个调试器(或没有)之后才显示出来。在第2版中,我们翻转了所有东西,这样UnhandledException事件在调试器附着之前触发,这似乎是大多数人所期望的。

这听起来像.NET 2.0更好(谢天谢地),但说实话,我从来没有时间回去检查。

1

这是一个Windows窗体应用程序。由Application.ThreadException捕获的异常工作正常,并且我没有得到丑陋的.NET异常框(OK终止,取消来调试?谁想出了这个??)。

我收到了一些未被捕获的异常,最终导致了导致问题的AppDomain.UnhandledException事件。我想我已经发现了大部分例外情况,现在我将它们显示在我们的错误框中。

所以我只需要希望没有其他一些情况会导致异常不被Application.ThreadException处理程序捕获。

4

AppDomain.UnhandledException事件,没有一个全球性的异常处理程序。这意味着,在提出时,您的应用程序已经耗尽,除了进行清理和错误日志记录之外,您无能为力。

幕后发生了什么事情:框架检测到异常,将调用堆栈放到最顶层,发现没有可以从错误中恢复的处理程序,所以无法确定继续执行是否安全。因此,它启动了关机程序,并向您发起了此活动,以便您可以向您已经注定的进程致敬。当主线程中发生异常时,会发生这种情况。

这种错误没有单点解决方案。您需要在发生此错误的所有位置上游放置一个真正的异常处理程序(catch块),并将其转发给(例如)全局处理程序方法/类,以确定是否安全地报告并继续,基于例外类型和/或内容。

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

5

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

  • 线程抛出异常
  • 无论是窗口消息处理
  • 期间是否发生一个调试器的类型被安装在处理
  • 的DbgJitDebugLaunchSetting注册表中App.Config中
  • 设置
  • 的jitDebugging标志210
  • 无论你推翻了Windows窗体异常处理程序
  • 无论您处理的CLR的异常事件
  • 月亮的相位

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

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

对未处理的异常的接触点是:

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

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

  • 捕捉到一个未处理的异常时:
    • 的例外是主线程和没有调试器连接。
    • 窗口消息处理期间发生异常。
    • jitDebugging =在App.Config中为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中,进入菜单工具选项调试JIT到此项设置为0或2,但值为1,通常最好是在最终用户的机。请注意,此注册表项在CLR未处理的异常事件之前执行。

这最后一个事件是您最后一次记录未处理异常的机会。它在Finally块执行之前触发。您可以如下拦截此事件:

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