views:

549

answers:

6

I'm working on a rather large project, and its unlikely will catch everything. I've found the event that notifies me of unhandled exceptions, however I haven't found a way to programmatically shut off the windows error dialog. Ideally, if there is an unhandled exception, I would like to have that event fired, provide a dialog box telling the user that there is a problem, and then to close gracefully. Is there any way to do this? I realize I could wrap the highest layer in a try catch, but I was hoping for something a little more elegant.

+3  A: 

This is what we did.

static void Main() {
    try
    {
        SubMain();
    }
    catch (Exception e)
    {
        HandleUnhandledException(e);
    }
}

private static void SubMain()
{
    // Setup unhandled exception handlers
    AppDomain.CurrentDomain.UnhandledException += // CLR
       new UnhandledExceptionEventHandler(OnUnhandledException);
     Application.ThreadException += // Windows Forms
       new System.Threading.ThreadExceptionEventHandler(
           OnGuiUnhandledException);
     Application.EnableVisualStyles();
     Application.SetCompatibleTextRenderingDefault(false);
     Application.Run(new frmMain());
}

// CLR unhandled exception
private static void OnUnhandledException(Object sender,
   UnhandledExceptionEventArgs e)
{
    HandleUnhandledException(e.ExceptionObject);
}

// Windows Forms unhandled exception
private static void OnGuiUnhandledException(Object sender,
   System.Threading.ThreadExceptionEventArgs e)
{
    HandleUnhandledException(e.Exception);
}
Aaron Smith
Why did I get downvoted?
Aaron Smith
Why do you implement both AppDomain.UnhandledException *and* wrap the entire thing in a Try/Catch block? That's silly goose.
Paul Betts
+1  A: 

http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx

Though if you're releasing this as a commercial project, I encourage you to register with Microsoft, so that you can actually get the crash dumps and error reporting info that is being sent to MS

Paul Betts
+2  A: 

You sort of answered your own question. The best way to prevent the error dialog is to write code that handles your exceptions so the dialog will never appear. I would wager this is what Raymond Chen would suggest (if I may be so bold).

Robert S.
A global try/catch (like the first answer) is what I was considering. I just wasn't sure if that was a best practice or not. I also wasn't sure if there was a cleaner way to do it.
Steve
A: 

You may try playing with HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AeDebug

That tip is form DrWatson days .. may or may not work.

Vardhan Varma
Don't muck with system-wide settings if you're trying to solve an app-specific problem
Paul Betts
- users may not like the fact that you change their settings... - Your application may not have write access to this registry key.
Julien N
A: 

If your question was in regards to a WinForms application then the selected answer will work for you, however it's not exactly elegant.

.NET provides an assistant for this exact scenario:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException)
AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf CurrentDomain_UnhandledException

And here's the MSDN Documentation on the method

STW
A: 

If you are using .NET framework 2.0 or later and there is an unhandled exception from a worker thread, I belive you're out of luck. In .NET 1.0 and 1.1, CLR simply swallowed the exception from a thread other than the main thread. However, this was changed in .NET 2.0 where an unhandled exception on a thread causes the application to shut down.

You can subscribe to AppDomain.CurrentDomain.UnhandledException to get notified when these kinds of unhandled exceptions occur but the application is most likely shutting down at this point and you're just given a chance to do things before the inevitable like logging the exception someplace and displaying user friendly message. UnhandledExceptionEventArgs has a readonly property called IsTerminating that you can inspect to see if the application is terminating or not. After the application terminates, usually Microsoft error reporting dialog pops up.

While I would not recommend this, there is a way to revert back to how CLR 1.0 and 1.1 were behaving by setting application compatibility flag in app config file.

This should not cause the application to terminate in cases of unhandled exceptions and reduce the likelihood of getting that error report dialog.

My recommendation would be to catch only the exceptions that you anticipate and able to handle in your code and let the other ones bubble up.

Mehmet Aras
It depends on how you manage your worker threads. My preferred approach for all non-long-running jobs is to use Delegate.BeginInvoke() to use a ThreadPool thread to perform the async action. If you do this then the thread will return any exception when you call EndInvoke()--you just have to make sure EndInvoke is called for every BeginInvoke (not doing so can lead to resource leaks of sorts).
STW