Click here to Skip to main content
15,867,453 members
Articles / Desktop Programming / Windows Forms
Article

A Simple Class to Catch Unhandled Exceptions in WinForms

Rate me:
Please Sign up or sign in to vote.
4.64/5 (30 votes)
25 Sep 20064 min read 198K   3.8K   168   25
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


Written By
Software Developer (Senior)
Russian Federation Russian Federation
More than 15 years in the industry.
Delphi, C# (Win/WebForms), MS SQL

Comments and Discussions

 
QuestionWorks great, even tho it's XP styled Pin
Eric Cristian Dumbrava16-Apr-23 22:38
Eric Cristian Dumbrava16-Apr-23 22:38 
QuestionLicense Pin
Member 1268188615-Feb-23 4:16
Member 1268188615-Feb-23 4:16 
QuestionSetUnhandledExceptionMode question Pin
boryakov26-Jun-12 0:52
boryakov26-Jun-12 0:52 
Generalabout MSDN: Working with Exceptions in .NET link Pin
GamePlanner27-Jul-10 23:44
GamePlanner27-Jul-10 23:44 
Generalreally helpful But not all exception Pin
aboelaraby5-Feb-08 7:28
aboelaraby5-Feb-08 7:28 
GeneralHI ,Reg Reading .Net Clr Exceptions Pin
Arun Kumar Babu26-Sep-07 0:40
Arun Kumar Babu26-Sep-07 0:40 
GeneralRe: HI ,Reg Reading .Net Clr Exceptions Pin
Vitaly Zayko28-Sep-07 8:13
Vitaly Zayko28-Sep-07 8:13 
QuestionJIT Debugging? Pin
AndrewVos10-Jan-07 23:10
AndrewVos10-Jan-07 23:10 
AnswerRe: JIT Debugging? Pin
Vitaly Zayko12-Jan-07 1:56
Vitaly Zayko12-Jan-07 1:56 
GeneralNo more try..catch. YEAH! :) Pin
Dabas10-Oct-06 17:42
Dabas10-Oct-06 17:42 
Good job Vitaly!

Thanks!

This will save quite a lot of time. No more typing in try..catch everywhere!



Daneil
GeneralRe: No more try..catch. YEAH! :) Pin
Vitaly Zayko11-Oct-06 1:23
Vitaly Zayko11-Oct-06 1:23 
QuestionOnShowErrorReport Pin
YoniP14-Sep-06 4:30
YoniP14-Sep-06 4:30 
AnswerRe: OnShowErrorReport Pin
Vitaly Zayko14-Sep-06 6:46
Vitaly Zayko14-Sep-06 6:46 
GeneralApplication.ThreadException Pin
cmaissan16-Aug-06 14:47
cmaissan16-Aug-06 14:47 
GeneralRe: Application.ThreadException [modified] Pin
Kel_17-Aug-06 7:29
Kel_17-Aug-06 7:29 
GeneralRe: Application.ThreadException Pin
Vitaly Zayko17-Aug-06 22:33
Vitaly Zayko17-Aug-06 22:33 
GeneralRe: Application.ThreadException Pin
Kel_20-Aug-06 7:04
Kel_20-Aug-06 7:04 
GeneralRe: Application.ThreadException Pin
Keith Vinson13-Sep-06 7:31
Keith Vinson13-Sep-06 7:31 
GeneralRe: Application.ThreadException Pin
Vitaly Zayko14-Sep-06 1:10
Vitaly Zayko14-Sep-06 1:10 
GeneralRe: Application.ThreadException Pin
Steve Hansen27-Sep-06 0:44
Steve Hansen27-Sep-06 0:44 
GeneralException in Visual Studio 2005 Pin
JK_net28-Jul-06 18:51
JK_net28-Jul-06 18:51 
GeneralRe: Exception in Visual Studio 2005 Pin
Vitaly Zayko30-Jul-06 3:58
Vitaly Zayko30-Jul-06 3:58 
GeneralUsefull Pin
NinjaCross25-Jul-06 2:43
NinjaCross25-Jul-06 2:43 
Newslook good but... Pin
pablleaf24-Jul-06 7:54
pablleaf24-Jul-06 7:54 
GeneralNice! Pin
machocr24-Jul-06 5:16
machocr24-Jul-06 5:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.