Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WinForms

A Simple Class to Catch Unhandled Exceptions in WinForms

4.64/5 (30 votes)
26 Sep 20064 min read 1   3.8K  
Explains how to catch an unhandled exception and send a stack trace along with other debug information to the developer.

Demo Screenshot

Introduction

Everyone knows how important exception handling is: no one wants to see meaningless messages, or application crashes, or even (often in the past) – “the blue screen of depth”. Fortunately, C#, just like probably all modern languages, has powerful try-catch-finally functions set that seemingly help to prevent common errors. But not in all cases.

Imagine that your app is using a bunch of third-party components or classes, and you don’t have their sources or even good documentation (that sounds familiar, doesn’t it?). In this case, the reliability of your app is based on the reliability of each class you have decided to use. Thus, you may even not know when to expect an exception and where to catch it. It is unlikely that you will catch all exceptions, especially if don’t know how to react to them.

On the other hand, it could be very useful to get error reports from users especially during the testing period. Microsoft has already included such functionality into its operating systems (see screenshot below), but all such reports will be sent to Microsoft not to the application developer whose app encountered the problem.

Microsoft Unhandled exception notification

Note: Actually there is a way of getting access to error information that is submitted to Microsoft for your customers: you can subscribe to Microsoft Windows Error Reporting service (see the link below). But this option is not cheap for small companies and single developers: you have to buy a digital certificate from VeriSign (starting $499).

Fortunately, .NET has such powerful functionality as the UnhandledException event so we can provide similar opportunity to be notified.

Using the Code

Let’s take a look closer at the UnhandledExceptionDlg class attached along with the demo for this article.

UnhandledExDlg Class diagram

First of all, we need to assign a handler to handle the Application.ThreadException event for the former, the AppDomain.CurrentDomain.UnhandledException event for the latter, and set Application.SetUnhandledExceptionMode to UnhandledExceptionMode.CatchException to force all Windows Forms errors to go through our handler, regardless of the settings in the application's user configuration file. UnhandledExDlg does it in its default constructor:

C#
Application.ThreadException += new 
  ThreadExceptionEventHandler(ThreadExceptionFunction);
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException += new 
  UnhandledExceptionEventHandler(UnhandledExceptionFunction);

The function UnhandledExceptionFunction takes the same parameters as AppDomain.CurrentDomain.UnhandledException which are object and UnhandledExceptionEventArgs, and returns void.

Basically, this function just puts some parameters such as event date/time, app name etc., sets "Restart Application" check box (see details below), and opens the dialog window.

The class has one public property bool RestartApp = true. This property correspond to the "Restart Application" check box on the Dialog and you, as a developer, should check its value, do some recovery work if needed.

To get user feedback, you should handle two class events: OnShowErrorReport and OnSendExceptionClick. The first one is linked to link label "Click here". This link shows the user the kind of information that is going to be sent. If you won't handle this event, then the link and its description will be hidden. OnSendExceptionClick is triggered when the user clicks on the "Send Report" button. You have to handle it to provide a transport to send the exception info. It could be HTTP POST, SMTP, FTP etc. If you won't handle this event, the button "Send Report" will be disabled. Here is an example of how to use these events:

C#
// Here is your react to user request to show him what information will be sent
exDlg.OnShowErrorReport += delegate(object sender, 
                           SendExceptionClickEventArgs ar)
{
    System.Windows.Forms.MessageBox.Show("Handle OnShowErrorReport" + 
           " event to show what you are going to send.\n" +
           "For example:\n" + ar.UnhandledException.Message + 
           "\n" + ar.UnhandledException.StackTrace + 
           "\n" + (ar.RestartApp ? "This App will be restarted." : 
           "This App will be terminated!"));
};

// Yes! User wants to send!
exDlg.OnSendExceptionClick += delegate(object sender, 
                              SendExceptionClickEventArgs ar)
{
    // User clicked on "Send Error Report" button:
    if(ar.SendExceptionDetails)
        // --- Implement your send transport here ---

    // User wants to restart the App:
    if(ar.RestartApp)
    {
        // --- Perform data restoration if needed and restart your App
        // System.Diagnostics.Process.Start(
        //        System.Windows.Forms.Application.ExecutablePath);
    }
};

The class SendExceptionClickEventArgs extends System.EventArgs, and has three additional parameters:

C#
// TRUE if user clicked on "Send Error Report"
// button and FALSE if on "Don't Send"
bool SendExceptionDetails;
// Used to store captured exception
Exception UnhandledException;
// Contains user's request: should the App to be restarted or not
bool RestartApp;

Just-In-Time Debugging

This is about how to suppress the Visual Studio JIT dialog window that opens every time when an unhandled exception is caught. If you want to suppress this dialog, you can uncheck “Enable the exception assistant” in the IDE’s “Debugging” section in the “Options” menu.

Microsoft Visual Studio 2005:

VS 2005 Options Dialog

Microsoft Visual Studio 2003:

VS 2003 Options Dialog

If you also want to disable the Windows “Send Error Report” dialog on your computer, right-click on the “My Computer” icon, select “Properties”, switch to the “Advanced” tab, and click on the “Error Reporting” button. In the Options dialog, select the “Disable error reporting” radio button:

Disable Error reporting

And that is all about UnhandledExceptionDlg. Please don't hesitate to submit your opinions and suggestions.

Points of Interest

History

  • September 26, 2006 - Added handling of ThreadException and SetUnhandledExceptionMode (thanks to everyone who brought that to my attention!). Demo project was updated as well.
  • August 29, 2006 - Updated information about the Microsoft Windows Error Reporting service and its link.
  • July 24, 2006 - Initial release.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here