我开发了.NET 4软件,我已准备好将其发送给测试版用户。如果在软件中抛出未处理的异常,我想抓住它,记录它并将日志发送给我。我已经实现了这个功能,当我在Visual Studio的调试模式下运行时,它似乎运行正常。但是,当我构建软件的发行版并安装它时,Microsoft .NET Framework开始在我的代码之前捕获异常。我收到一个错误消息的弹出窗口:“应用程序中的组件中发生了未处理的异常。如果单击继续,应用程序将忽略此错误并尝试继续。”
为了测试崩溃,我创建了一个崩溃按钮,它会抛出异常。此崩溃记录自身,异常处理程序记录所有收到的未处理异常。当我查看发布版本的日志时,我只能看到崩溃时的日志消息,而不是异常处理程序中的日志消息。
我已使用此代码附加了自己的异常处理程序:
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
是否有某种方法可以禁用.NET Framework的异常捕获,或者是否有更好的方法来附加我自己的异常处理程序?
更新:我正在使用WPF。我将查看DispatcherUnhandledException并告诉您它是否解决了问题。
UPDATE#2:不幸的是,向Application.Current.DispatcherUnhandledException添加处理程序并没有解决问题。显然,这个调试弹出窗口是由Visual Studio附带的JIT(实时)调试器创建的。我将不得不用“民用”Windows测试软件,看看是否也有例外。
UPDATE#3:由于某种原因,使用Visual Studio构建的版本可以正常工作,但使用MSBuild脚本和Dotfuscator构建的版本不能。
答案 0 :(得分:6)
您尚未指定正在使用的框架,但还有其他“未处理的例外”事件。
对于Windows窗体,有Application.ThreadException
。
对于WPF / Silverlight,有Application.DispatcherUnhandledException
。
首先尝试其中一个,如果您仍然遇到问题,请告诉我们。
答案 1 :(得分:5)
我终于解决了这个问题。问题不是由于收听错误的异常引起的,而是由于发布版本中缺少DLL。
在为DispatchedUnhandledException和ThreadException事件添加侦听器后,我不再使用奇怪的Microsoft .NET Framework弹出窗口,该弹出窗口允许用户在异常后继续运行该软件。然而,我自己的异常处理在这一点上仍然被打破。
因为在异常处理程序应该启动时软件已经崩溃了,所以我在异常处理程序周围有一个catch(Exception)。删除此catch后,我终于得到了发布版本的正确错误消息,并添加了缺少的DLL。
我(再次)学到的教训是:不要使用空捕获(异常)块。这很邪恶。
答案 2 :(得分:4)
听起来好像正在冒泡到你的应用程序的消息循环中。在Windows窗体中,您可以通过为Application.ThreadException事件设置事件处理程序来处理这些问题。在WPF / Silverlight中,等效事件为Application.DispatcherUnhandledException。
您也可以在Main方法中放置一个try / catch(如果有的话)以获得良好的衡量标准,但UI通常会在您注意到时首先捕获异常。
修改强>
在WPF / Silverlight中,设置e.Handled = true以防止异常继续向上移动。
答案 3 :(得分:2)
...哎哟
Dotfuscator 可能会生成一个无法JIT的无效程序集。用户代码永远不会捕获JIT异常。这类似于无法捕获StackOverflowException
的方式,因为运行时无法保证它可以安全地从遇到的错误条件中恢复。
尽管如此,由于IL和JITer之间存在各种验证阶段,因此在运行时很可能无法获得JIT异常。也许你有InvalidProgramException
或BadImageFormatException
?如果JITter确实失败了,这很可能是运行时中的错误,不应该发生。
无论如何,你可以检查两件事:
答案 4 :(得分:1)
您可以查看AppDomain class and the UnhandledException事件和Application.ThreadException event。这些将捕获未处理的异常,就像您使用try-catch块处理自己的异常一样,您可以编写一个帮助程序类来管理异常并使用它们执行所需的操作。您甚至可以在该类中编写第三个事件来处理异常。
答案 5 :(得分:1)
// 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.
答案 6 :(得分:0)
try ... catch
中Main()
会阻止吗?
答案 7 :(得分:0)
来自UnhandledException事件的文档,
此事件提供通知 没有被捕的例外。它允许 应用程序记录有关的信息 系统之前的例外 默认处理程序报告异常 给用户并终止 应用
这只是一种钩子方法,您可以在默认错误报告机制启动之前插入自定义代码。未处理的异常将始终关闭您的进程。它不允许您替换整个行为。
我首先质疑你的任务背后的需要。
最简单的方法是采用一个团队约定,Main和所有Thread函数都有一个封闭的try-catch
似乎有新的类型+事件(DispatcherUnhandledException)来捕获未处理的异常,但我会质疑它是否值得它所带来的复杂性。它应该是最后一道防线,而不是主要防线。
例如如果在另一个线程中发生未处理的异常,则需要更多代码(因为异常不会跨线程路由,而且它只是终止进程)。