windows 如何禁用 .NET Framework 异常处理并改用我自己的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3732823/
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
How to disable .NET Framework exception handling and use my own instead?
提问by Ville Salonen
I've developed a .NET 4 software and I'm ready to send it to beta users. If an unhandled exception is thrown in the software, I would like to catch it, log it and send the logs to me. I've already implemented this functionality and it seems to be running fine when I run it in debug mode with Visual Studio. However, when I've built a release version of the software and installed it, Microsoft .NET Framework starts to catch exceptions before my code. I get a popup with an error message: "Unhandled exception has occurred in a component in your application. If you click Continue, the application will ignore this error and attempt to continue."
我已经开发了一个 .NET 4 软件,我准备将它发送给测试版用户。如果软件中抛出未处理的异常,我想捕获它,记录它并将日志发送给我。我已经实现了这个功能,当我使用 Visual Studio 在调试模式下运行它时,它似乎运行良好。但是,当我构建并安装了该软件的发布版本时,Microsoft .NET Framework 开始在我的代码之前捕获异常。我收到一个带有错误消息的弹出窗口:“应用程序的组件中发生了未处理的异常。如果单击继续,应用程序将忽略此错误并尝试继续。”
To test the crashing, I created a crash down button which throws an exception. This crash down logs itself and the exception handler logs all received unhandled exceptions. When I look at the log of the release version, I can only see the log message from crash down but not from the exception handler.
为了测试崩溃,我创建了一个抛出异常的崩溃按钮。这次崩溃会记录自己,异常处理程序会记录所有收到的未处理的异常。当我查看发布版本的日志时,我只能看到崩溃的日志消息,而看不到异常处理程序的日志消息。
I've attached my own exception handler with this code:
我已经使用以下代码附加了我自己的异常处理程序:
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Is there some way to disable the exception catching of .NET Framework or is there a better way to attach my own exception handler?
有什么方法可以禁用 .NET Framework 的异常捕获,还是有更好的方法来附加我自己的异常处理程序?
UPDATE:I'm using WPF. I'll look into the DispatcherUnhandledException and let you know if it solves the problem.
更新:我正在使用 WPF。我将查看 DispatcherUnhandledException 并让您知道它是否解决了问题。
UPDATE #2:Unfortunately adding handler to Application.Current.DispatcherUnhandledException didn't solve the problem. Apparently this debugging popup is created by JIT (Just-In-Time) debugger which is included with Visual Studio. I'll have to test the software with a "civilian" Windows and see if the exceptions are catched there too.
更新 #2:不幸的是,向 Application.Current.DispatcherUnhandledException 添加处理程序并没有解决问题。显然,此调试弹出窗口是由 Visual Studio 中包含的 JIT(即时)调试器创建的。我将不得不使用“民用”Windows 测试该软件,看看是否也能在那里捕获异常。
UPDATE #3:For some reason the Release built with Visual Studio works but the Release built with MSBuild scripts and Dotfuscator does not.
更新 #3:出于某种原因,使用 Visual Studio 构建的 Release 有效,但使用 MSBuild 脚本和 Dotfuscator 构建的 Release 无效。
采纳答案by Ville Salonen
I finally solved the problem. The problem was not caused by listening to wrong exceptions but due to missing a DLL from the released version.
我终于解决了这个问题。该问题不是由侦听错误的异常引起的,而是由于缺少已发布版本的 DLL。
After adding listeners for DispatchedUnhandledException and ThreadException events I no longer got the strange Microsoft .NET Framework popup which allowed the user to continue running the software after exception. However my own exception handling was still broken at this point.
在为 DispatchedUnhandledException 和 ThreadException 事件添加侦听器后,我不再看到奇怪的 Microsoft .NET Framework 弹出窗口,它允许用户在异常后继续运行软件。然而,我自己的异常处理在这一点上仍然被打破。
Because the software was already crashing down at the moment when the exception handler was supposed to kick in, I had a catch (Exception) around the exception handler. After removing this catch I finally got the correct error message with release version and added the missing DLLs.
因为在异常处理程序应该启动的那一刻软件已经崩溃了,所以我在异常处理程序周围有一个捕获(异常)。删除这个 catch 后,我终于得到了正确的错误消息和发布版本,并添加了丢失的 DLL。
The lesson I learned (again) is: do not use empty catch (Exception) block. It is evil.
我(再次)学到的教训是:不要使用空的 catch (Exception) 块。它是邪恶的。
回答by Jon Skeet
You haven't specified which framework you're using, but there are other "unhandled exception" events around.
您尚未指定正在使用的框架,但还有其他“未处理的异常”事件。
For Windows Forms, there's Application.ThreadException
.
对于 Windows 窗体,有Application.ThreadException
.
For WPF/Silverlight there's Application.DispatcherUnhandledException
.
对于 WPF/Silverlight,有Application.DispatcherUnhandledException
.
Try one of those two first, and let us know if you're still having problems.
首先尝试这两个中的一个,如果您仍然遇到问题,请告诉我们。
回答by Josh
It sounds like the exception is bubbling out to your application's message loop. In Windows Forms, you can handle these by setting up an event handler for Application.ThreadExceptionevent. In WPF/Silverlight, the equivalent event would be Application.DispatcherUnhandledException.
听起来异常正在冒泡到您的应用程序的消息循环中。在 Windows 窗体中,您可以通过为Application.ThreadException事件设置事件处理程序来处理这些问题。在 WPF/Silverlight 中,等效的事件是Application.DispatcherUnhandledException。
You can also put a try/catch in your Main method (if you have one) for good measure but the UI will usually catch the exceptions first as you've noticed.
您也可以在 Main 方法(如果有的话)中放置一个 try/catch 以进行良好的衡量,但 UI 通常会像您注意到的那样首先捕获异常。
EDIT
编辑
In WPF/Silverlight, set e.Handled = true to prevent the exception from continuing up the stack.
在 WPF/Silverlight 中,设置 e.Handled = true 以防止异常继续向上堆栈。
回答by Johannes Rudolph
Ouch...
Dotfuscator mightgenerate you an invalid assembly that is not JIT'able. JIT exceptions can never be caught by user code. This is similar to the way you cannot catch StackOverflowException
because the runtime cannot guarantee you it can safely recover from the encountered error condition.
哎哟... Dotfuscator可能会为您生成一个无法 JIT 的无效程序集。用户代码永远无法捕获 JIT 异常。这类似于您无法捕获的方式,StackOverflowException
因为运行时无法保证您可以安全地从遇到的错误情况中恢复。
Nonetheless, it is very unlikely you get a JIT exception at runtime since there are various stages of validation in between your IL and the JITer. Maybe you got an InvalidProgramException
or a BadImageFormatException
? If the JITter is really failing this is most likely a bug in the runtime and shouldn't happen.
尽管如此,您不太可能在运行时遇到 JIT 异常,因为在您的 IL 和 JITer 之间存在不同的验证阶段。也许你有一个InvalidProgramException
或一个BadImageFormatException
?如果 JITter 真的失败了,这很可能是运行时中的错误,不应该发生。
Anyway, two things you can check:
无论如何,您可以检查两件事:
- Run PEVerify on your broken/working assembly and compare the output.
- Try NGEN on your broken assembly to see if you can provoke the error.
- 在损坏的/工作的组件上运行 PEVerify 并比较输出。
- 在损坏的程序集上尝试 NGEN,看看是否会引发错误。
回答by David Anderson
You can look into the AppDomain class and the UnhandledExceptionevent and Application.ThreadException event. These will catch unhandled exceptions, as for exceptions you are handling yourself with a try-catch block, you could write a helper class to manage your exceptions and do what you need with them. You could even write a third event in that class for handled exceptions.
您可以查看AppDomain 类以及 UnhandledException事件和Application.ThreadException 事件。这些将捕获未处理的异常,对于您自己使用 try-catch 块处理的异常,您可以编写一个帮助类来管理您的异常并使用它们做您需要的操作。您甚至可以在该类中编写第三个事件来处理异常。
回答by dpminusa
// Add the event handler for handling UI thread exceptions to Windows Form Events.
// Uses SystemThreading.
// NOTE: Remember to turn Execption Handler OFF in the Debugger for testing!! Debug -> Common Language Runtime Exceptions -> User-Unhandled -> OFF.
// NOTE: A separate Event Handler is Needed for other threads added to the Application.
// NOTE: Methods can catch, inform, then throw for logging and emailing as well.
// Add these to Program.cs.
static void Main()
{
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
// Set the unhandled exception mode to force all Windows Forms errors to go through the Handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// ...
}
// Then put your handler in the method referenced in the event definition above.
static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
// Your Code ...
}
// Sorry for the ragged listing. Still getting used to the editor here.
回答by Andrew Cooper
Would a try ... catch
block in Main()
help?
将一个try ... catch
块Main()
的帮助?
回答by Gishu
From the documentation of UnhandledException event,
从 UnhandledException 事件的文档中,
This event provides notification of uncaught exceptions. It allows the application to log information about the exception before the system default handler reports the exception to the user and terminates the application.
此事件提供未捕获异常的通知。它允许应用程序在系统默认处理程序向用户报告异常并终止应用程序之前记录有关异常的信息。
It is just a hook method where you can insert your custom code code, before the default error reporting mechanism kicks in. An unhandled exception will always take down your process. It doesn't allow you to replace the whole behavior.
它只是一个钩子方法,您可以在其中插入您的自定义代码代码,在默认错误报告机制启动之前。未处理的异常总是会中断您的进程。它不允许您替换整个行为。
I'd first question the need behind your quest..
The simplest approach is to just adopt a team convention that Main and all Thread Functions have an enclosing try-catch.
There seem to be new types+events(DispatcherUnhandledException) to catch unhandled exceptions, but I'd question if its worth the complexity it drags in. It should be a last-line of defence, not the primary one.
e.g. if an unhandled exception occurs in a different thread, you'd need more code (since exceptions are not routed across threads & it'd just terminate the process).
我首先质疑您的追求背后的需求。
最简单的方法是采用团队约定,即 Main 和所有线程函数都有一个封闭的 try-catch。
似乎有新的类型 + 事件(DispatcherUnhandledException)来捕获未处理的异常,但我怀疑它是否值得它拖入的复杂性。它应该是最后一道防线,而不是主要防线。
例如,如果未处理的异常发生在不同的线程中,您需要更多的代码(因为异常不会跨线程路由,它只会终止进程)。