是否有一个设置阻止未处理的异常对话框显示在我编译的应用程序中?

时间:2012-07-21 09:27:17

标签: c# .net visual-studio-2010

我不确定这是否是正确的地方,但无论如何我都会。

我有2个.NET应用程序;一个是我自己编写的,另一个不是。两者都使用.NET Framework 4.5。但他们以不同的方式处理异常。

在我没编译的应用程序中;它显示了未处理的异常对话框(我想要并期望)

Unhandled Exception from app I didnt compile

但是在我编译的应用程序中;它只是显示应用程序已崩溃;

Unhandled Exepction from app I compiled

因此,VS配置或项目配置中必须有一个设置阻止未处理的异常对话框在我编译的应用程序中显示?...

我尝试重新安装VS,更改Debug-> Exceptions菜单中的设置,但都没有工作......

2 个答案:

答案 0 :(得分:12)

顶部屏幕截图是一个ThreadExceptionDialog。它显示在一个非常特殊的情况下,Winforms应用程序在由消息循环(Application.Run)触发的事件处理程序中炸弹,并且应用程序没有重新分配Application.ThreadException事件处理程序。使用它不是一个很好的做法,用户无法确定是否单击“继续”或“退出”按钮。一定要调用Application.SetUnhandledExceptionMode()来禁用它。

底部屏幕截图是默认的Windows错误报告对话框,当程序遭遇未处理的异常时,Windows会显示该对话框。你应该永远让它到达这一点,对话框没有显示足够的信息来帮助任何人诊断和解决问题。始终为AppDomain.CurrentDomain.UnhandledException事件编写事件处理程序。显示和/或记录e.ExceptionObject.ToString()并调用Environment.Exit()来终止应用程序。

使您的Program.cs源代码看起来类似于:

    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
        Application.Run(new Form1());
    }

    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
        // TODO: improve logging and reporting
        MessageBox.Show(e.ExceptionObject.ToString());
        Environment.Exit(-1);
    }

答案 1 :(得分:2)

Hans Passant提出的解决方案将终止申请。这也意味着不再执行剩余的finally块。

您还可以使用PInvoke通过调用SetErrorMode()方法来更改行为。

public enum ErrorModes : uint
{
    SYSTEM_DEFAULT = 0x0,
    SEM_FAILCRITICALERRORS = 0x0001,
    SEM_NOALIGNMENTFAULTEXCEPT = 0x0004,
    SEM_NOGPFAULTERRORBOX = 0x0002,
    SEM_NOOPENFILEERRORBOX = 0x8000,
    SEM_NONE = SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX
}

[DllImport("kernel32.dll")]
static extern ErrorModes SetErrorMode(ErrorModes uMode);

然后致电

SetErrorMode(ErrorModes.SEM_NONE);

这样做会使finally块有机会运行。