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

时间:2008-08-04 01:15:38

标签: c# .net exception exception-handling

我正在维护一个.NET 1.1应用程序,其中一项任务就是确保用户没有看到任何不友好的错误通知。

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

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

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

5 个答案:

答案 0 :(得分:11)

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

我在这里有一篇旧代码项目文章应该有所帮助:

User Friendly Exception Handling

答案 1 :(得分:5)

AppDomain.UnhandledException 事件,而不是全局异常处理程序。这意味着,当它被引发时,你的应用程序已经开始流失了,除了进行清理和错误记录之外,你无能为力。

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

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

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

答案 2 :(得分:5)

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

  • 抛出异常的线程类型
  • 是否在窗口消息处理期间发生
  • 调试器是否附加到流程
  • DbgJitDebugLaunchSetting注册表设置
  • App.Config中的jitDebugging标志
  • 是否覆盖Windows窗体异常处理程序
  • 您是否处理了CLR的异常事件
  • 月亮的阶段

未处理的例外的默认行为是:

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

未处理例外的联系点是:

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

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

  • 在以下情况下捕获未处理的异常:
    • 异常在主线程上,没有附加调试器。
    • 在窗口消息处理期间发生
    • 异常。
    • 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中,转到菜单工具选项调试 JIT 将此键设置为0或2.但值1通常最终用户的机器上。请注意,在CLR未处理的异常事件之前,将对此注册表项执行操作。

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

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

答案 3 :(得分:3)

这是控制台应用程序还是Windows窗体应用程序?如果它是一个.NET 1.1控制台应用程序,遗憾的是,这是设计 - 它由second blog post you referenced中的MSFT开发人员确认:

  

BTW,在我的1.1机器上,来自MSDN的示例确实具有预期的输出;只是在你连接调试器之后才显示第二行(或不是)。在v2中,我们已经翻转了一些东西,以便在调试器附加之前触发UnhandledException事件,这似乎是大多数人所期望的。

听起来.NET 2.0做得更好(谢天谢地),老实说,我没有时间回去检查。

答案 4 :(得分:1)

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

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

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