8

I'm not sure if this is the right place to ask but I shall anyway.

I have 2 .NET applications; one that was compiled by myself, the other not. Both use .NET Framework 4.5. But they handle exceptions differently.

In the application which I did NOT compile; it shows the unhandled exception dialog (which I want and expect)

Unhandled Exception from app I didnt compile

But in the application I did compile; it just shows the application has crashed;

Unhandled Exepction from app I compiled

So there must be a setting in the VS config or project config that is preventing the unhandled exception dialog from displaying in apps that I compile?...

I have tried re-installing VS, changing the settings in the Debug->Exceptions menu, neither have worked...

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
craig1231
  • 3,769
  • 4
  • 31
  • 34

2 Answers2

12

The top screen-shot is a ThreadExceptionDialog. It is displayed in the very specific case where a Winforms app bombs in an event handler that was fired by the message loop (Application.Run) and the app didn't otherwise reassign the Application.ThreadException event handler. Using it is not a very good practice, there's no reasonable way the user could know whether to click the Continue or Quit button. Be sure to call Application.SetUnhandledExceptionMode() to disable it.

The bottom screen-shot is the default Windows error reporting dialog, displayed by Windows when a program bombed on an unhandled exception. You should never let it get to this point, the dialog doesn't display enough information to help anybody diagnose and fix the problem. Always write an event handler for the AppDomain.CurrentDomain.UnhandledException event. Display and/or log e.ExceptionObject.ToString() and call Environment.Exit() to terminate the app.

Make your Program.cs source code look similar to this:

    [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);
    }
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • This does make sense, I forced the crash test to throw an exception when it was loaded, putting a button in the form and throwing an exception when the button was clicked invokes the unhandled exception dialog. Would you be able to provide more information how I could write an exception handler? Thanks – craig1231 Jul 21 '12 at 10:07
  • Interesting side effect: Once `Application.Run` returns, your `ThreadException` handler might no longer be subscribed and cause you to see the thread exception dialog. Keep that in mind if you call `Application.Run` more than once (which might not be a good idea in the first place). – stakx - no longer contributing Jun 18 '14 at 12:17
2

The solution presented by Hans Passant will terminate the application. This also means that remaining finally blocks are not executed any more.

You can also use PInvoke to change the behavior by calling the SetErrorMode() method.

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);

and then call

SetErrorMode(ErrorModes.SEM_NONE);

Doing so will give the finally blocks the chance to run.

Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
  • To disable only Windows Error Reporting dialog and crash report, one can use `SetErrorMode(SetErrorMode(0) | ErrorModes.SEM_NOGPFAULTERRORBOX)`. – jramos Aug 26 '19 at 04:26