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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/944/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-07-31 12:09:31  来源:igfitidea点击:

Unhandled Exception Handler in .NET 1.1

提问by Ray

I'm maintaining a .NET 1.1 application and one of the things I've been tasked with is making sure the user doesn't see any unfriendly error notifications.

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

I've added handlers to Application.ThreadExceptionand AppDomain.CurrentDomain.UnhandledException, which do get called. My problem is that the standard CLR error dialog is still displayed (before the exception handler is called).

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

Jeff talks about this problem on his blog hereand here. But there's no solution. So what is the standard way in .NET 1.1 to handle uncaught exceptions and display a friendly dialog box?

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

Jeff's response was marked as the correct answer because the link he provided has the most complete information on how to do what's required.

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

采纳答案by Jeff Atwood

Oh, in Windows Forms you definitely should be able to get it to work. The only thing you have to watch out for is things happening on different threads.

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

I have an old Code Project article here which should help:

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

User Friendly Exception Handling

用户友好的异常处理

回答by Jeff Atwood

Is this a console application or a Windows Forms application? If it's a .NET 1.1 console application this is, sadly, by design -- it's confirmed by an MSFT dev in the second blog post you referenced:

这是控制台应用程序还是 Windows 窗体应用程序?如果它是 .NET 1.1 控制台应用程序,遗憾的是,这是设计使然——MSFT 开发人员在您引用第二篇博文中证实了这一点:

BTW, on my 1.1 machine the example from MSDN does have the expected output; it's just that the second line doesn't show up until after you've attached a debugger (or not). In v2 we've flipped things around so that the UnhandledException event fires before the debugger attaches, which seems to be what most people expect.

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

It sounds like .NET 2.0 does this better (thank goodness), but honestly, I never had time to go back and check.

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

回答by Ray

It's a Windows Forms application. The exceptions that are caught by Application.ThreadException work fine, and I don't get the ugly .NET exception box (OKto terminate, Cancelto debug? who came up with that??).

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

I was getting some exceptions that weren't being caught by that and ended up going to the AppDomain.UnhandledException event that were causing problems. I think I've caught most of those exceptions, and I am displaying them in our nice error box now.

我收到了一些没有被它捕获的异常,最终转到了导致问题的 AppDomain.UnhandledException 事件。我想我已经捕获了大部分异常,现在我将它们显示在我们漂亮的错误框中。

So I'll just have to hope there are not some other circumstances that would cause exceptions to not be caught by the Application.ThreadException handler.

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

回答by Ishmaeel

AppDomain.UnhandledExceptionis an event, not a global exception handler. This means, by the time it is raised, your application is already on its way down the drain, and there is nothing you can do about it, except for doing cleanup and error logging.

AppDomain.UnhandledException是一个事件,而不是全局异常处理程序。这意味着,当它被启动时,您的应用程序已经在消耗殆尽,除了清理和错误日志之外,您无能为力。

What happened behind the scenes is this: The framework detected the exception, walked up the call stack to the very top, found no handlers that would recover from the error, so was unable to determine if it was safe to continue execution. So, it started the shutdown sequence and fired up this event as a courtesy to you so you can pay your respects to your already-doomed process. This happens when an exception is left unhandled in the main thread.

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

There is no single-point solution to this kind of error. You need to put a real exception handler (a catch block) upstream of all places where this error occurs and forward it to (for example) a global handler method/class that will determine if it is safe to simply report and continue, based on exception type and/or content.

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

Edit: It is possible to disable (=hack) the error-reporting mechanism built into Windows so the mandatory "crash and burn" dialog does not get displayed when your app goes down. However, this becomes effective for allthe applications in the system, not just your own.

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

回答by HTTP 410

Unhandled exception behavior in a .NET 1.x Windows Forms application depends on:

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

  • The type of thread that threw the exception
  • Whether it occurred during window message processing
  • Whether a debugger was attached to the process
  • The DbgJitDebugLaunchSetting registry setting
  • The jitDebugging flag in App.Config
  • Whether you overrode the Windows Forms exception handler
  • Whether you handled the CLR's exception event
  • The phase of the moon
  • 抛出异常的线程类型
  • 是否发生在窗口消息处理过程中
  • 调试器是否附加到进程
  • DbgJitDebugLaunchSetting 注册表设置
  • App.Config 中的 jitDebugging 标志
  • 是否覆盖了 Windows 窗体异常处理程序
  • 是否处理了 CLR 的异常事件
  • 月相

The default behavior of unhandled exceptions is:

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

  • If the exception occurs on the main thread when pumping window messages, it's intercepted by the Windows Forms exception handler.
  • If the exception occurs on the main thread when pumping window messages, it will terminate the app process unless it's intercepted by the Windows Forms exception handler.
  • If the exception occurs on a manual, thread-pool, or finalizer thread, it's swallowed by the CLR.
  • 如果在泵送窗口消息时主线程上发生异常,则会被 Windows 窗体异常处理程序拦截。
  • 如果在泵送窗口消息时主线程上发生异常,它将终止应用进程,除非它被 Windows 窗体异常处理程序拦截。
  • 如果异常发生在手动、线程池或终结器线程上,则它会被 CLR 吞下。

The points of contact for an unhandled exception are:

未处理异常的联系点是:

  • Windows Forms exception handler.
  • The JIT-debug registry switch DbgJitDebugLaunchSetting.
  • The CLR unhandled exception event.
  • Windows 窗体异常处理程序。
  • JIT 调试注册表开关 DbgJitDebugLaunchSetting。
  • CLR 未处理的异常事件。

The Windows Form built-in exception handling does the following by default:

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

  • Catches an unhandled exception when:
    • exception is on main thread and no debugger attached.
    • exception occurs during window message processing.
    • jitDebugging = false in App.Config.
  • Shows dialog to user and prevents app termination.
  • 在以下情况下捕获未处理的异常:
    • 异常发生在主线程上,并且没有附加调试器。
    • 窗口消息处理期间发生异常。
    • App.Config 中的 jitDebugging = false。
  • 向用户显示对话框并防止应用程序终止。

You can disable the latter behavior by setting jitDebugging = true in App.Config. But remember that this may be your last chance to stop app termination. So the next step to catch an unhandled exception is registering for event Application.ThreadException, e.g.:

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

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

Note the registry setting DbgJitDebugLaunchSetting under HKEY_LOCAL_MACHINE\Software.NetFramework. This has one of three values of which I'm aware:

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

  • 0: shows user dialog asking "debug or terminate".
  • 1: lets exception through for CLR to deal with.
  • 2: launches debugger specified in DbgManagedDebugger registry key.
  • 0:显示用户对话框询问“调试或终止”。
  • 1:让异常通过CLR来处理。
  • 2:启动在 DbgManagedDebugger 注册表项中指定的调试器。

In Visual Studio, go to menu ToolsOptionsDebuggingJITto set this key to 0 or 2. But a value of 1 is usually best on an end-user's machine. Note that this registry key is acted on before the CLR unhandled exception event.

在 Visual Studio 中,转到菜单ToolsOptionsDebuggingJIT将此键设置为 0 或 2。但值 1 通常在最终用户的机器上最好。请注意,此注册表项在 CLR 未处理异常事件之前执行。

This last event is your last chance to log an unhandled exception. It's triggered before your Finally blocks have executed. You can intercept this event as follows:

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

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