.NET 1.1 中未处理的异常处理程序
-
08-06-2019 - |
解决方案
其他提示
AppDomain.UnhandledException 是一个 事件, ,不是全局异常处理程序。这意味着,当它被引发时,您的应用程序已经陷入困境,除了进行清理和错误日志记录之外,您对此无能为力。
幕后发生的事情是这样的:框架检测到异常,将调用堆栈向上移动到最顶部,发现没有可以从错误中恢复的处理程序,因此无法确定继续执行是否安全。因此,它启动了关闭序列,并出于对您的礼貌而启动了此事件,以便您可以向已经注定的进程表示敬意。当主线程中未处理异常时会发生这种情况。
对于此类错误没有单点解决方案。您需要在发生此错误的所有位置的上游放置一个真正的异常处理程序(catch 块),并将其转发到(例如)全局处理程序方法/类,该方法/类将确定简单地报告并继续是否安全,基于异常类型和/或内容。
编辑:可以禁用(=破解)Windows 内置的错误报告机制,这样当您的应用程序出现故障时,就不会显示强制的“崩溃并烧毁”对话框。然而,这对于 全部 系统中的应用程序,而不仅仅是您自己的应用程序。
.NET 1.x Windows 窗体应用程序中未处理的异常行为取决于:
- 抛出异常的线程类型
- 是否发生在窗口消息处理过程中
- 进程是否附加了调试器
- DbgJitDebugLaunchSetting 注册表设置
- App.Config 中的 jitDebugging 标志
- 是否覆盖 Windows 窗体异常处理程序
- 是否处理了CLR的异常事件
- 月相
未处理异常的默认行为是:
- 如果在泵送窗口消息时主线程上发生异常,则 Windows 窗体异常处理程序会拦截该异常。
- 如果在泵送窗口消息时主线程发生异常,它将终止应用程序进程,除非它被 Windows 窗体异常处理程序拦截。
- 如果异常发生在手动、线程池或终结器线程上,则会被 CLR 吞掉。
未处理异常的联系点是:
- Windows 窗体异常处理程序。
- JIT 调试注册表开关 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 中,转到菜单 工具 → 选项 → 调试 → 准时生产 将此键设置为 0 或 2。但对于最终用户的计算机来说,值 1 通常是最好的。请注意,此注册表项在 CLR 未处理异常事件之前执行。
最后一个事件是您记录未处理异常的最后机会。它是在执行 Final 块之前触发的。您可以按如下方式拦截此事件:
AppDomain.CurrentDomain.UnhandledException += new
System.UnhandledExceptionEventHandler(CatchClrExceptions);
这是控制台应用程序还是 Windows 窗体应用程序?不幸的是,如果它是一个 .NET 1.1 控制台应用程序,这是设计使然的——它已被 MSFT 开发人员证实 您引用的第二篇博文:
顺便说一句,在我的 1.1 机器上,MSDN 中的示例确实具有预期的输出;只是第二行只有在附加调试器(或不附加)后才会显示。在 v2 中,我们颠倒了一些事情,以便在调试器附加之前触发 UnhandledException 事件,这似乎是大多数人所期望的。
听起来 .NET 2.0 在这方面做得更好(谢天谢地),但说实话,我从来没有时间回去检查。
它是一个 Windows 窗体应用程序。Application.ThreadException 捕获的异常工作正常,并且我没有得到丑陋的 .NET 异常框(好的 终止, 取消 调试?谁想出来的??)。
我收到了一些没有被捕获的异常,并最终进入导致问题的 AppDomain.UnhandledException 事件。我想我已经捕获了大部分异常,并且现在将它们显示在我们漂亮的错误框中。
因此,我只希望没有其他情况会导致异常不被 Application.ThreadException 处理程序捕获。