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.
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.
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:
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:
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!"));
};
exDlg.OnSendExceptionClick += delegate(object sender,
SendExceptionClickEventArgs ar)
{
if(ar.SendExceptionDetails)
if(ar.RestartApp)
{
}
};
The class SendExceptionClickEventArgs
extends System.EventArgs
, and has three additional parameters:
bool SendExceptionDetails;
Exception UnhandledException;
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:
Microsoft Visual Studio 2003:
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:
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.