如何禁用.NET Framework异常处理并使用我自己的异常处理?

时间:2010-09-17 05:22:59

标签: c# .net windows exception

我开发了.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构建的版本不能。

8 个答案:

答案 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异常。也许你有InvalidProgramExceptionBadImageFormatException?如果JITter确实失败了,这很可能是运行时中的错误,不应该发生。

无论如何,你可以检查两件事:

  1. 在破损/工作装配上运行PEVerify并比较输出。
  2. 在破损的组件上尝试NGEN,看看是否可以引发错误。

答案 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 ... catchMain()会阻止吗?

答案 7 :(得分:0)

来自UnhandledException事件的文档,

  

此事件提供通知   没有被捕的例外。它允许   应用程序记录有关的信息   系统之前的例外   默认处理程序报告异常   给用户并终止   应用

这只是一种钩子方法,您可以在默认错误报告机制启动之前插入自定义代码。未处理的异常将始终关闭您的进程。它不允许您替换整个行为。

我首先质疑你的任务背后的需要。
最简单的方法是采用一个团队约定,Main和所有Thread函数都有一个封闭的try-catch 似乎有新的类型+事件(DispatcherUnhandledException)来捕获未处理的异常,但我会质疑它是否值得它所带来的复杂性。它应该是最后一道防线,而不是主要防线。 例如如果在另一个线程中发生未处理的异常,则需要更多代码(因为异常不会跨线程路由,而且它只是终止进程)。