Deborah's Developer MindScape






         Tips and Techniques for Web and .NET developers.

September 2, 2009

Global Exception Handler (WinForms)

Filed under: C#,Debugging,VB.NET @ 2:52 pm

Application failures will occur. The user could perform a sequence of
operations or enter a value that you don’t expect, the connectivity to your
database could be interrupted, the code could have a logic error, or many
other possibilities. The .NET Framework provides structure exception
handling (SEH) to help you manage application failures.

An exception is a failure that occurs in your application. Exceptions
fall into two broad categories: expected and unexpected.

Expected exceptions are those that your application plans for and
responds to. For example, you expect that a user-requested customer may
not be found in the database. So you add code to check for this condition
and respond with an appropriate message to the user.

Unexpected exceptions are those that you know may happen, but
don’t necessarily know when or where. These are more difficult to plan for.
Logic errors are a good example of this type of exception. This is especially
true in cases where the logic error corrupts some underlying data and the
exception occurs later when that data is processed, possibly far from the
actual logic error.

Structured exception handling allows you to define a code structure
to handle both expected and unexpected exceptions generated in your application. This is the purpose of the Try/Catch blocks provided in the .NET
Framework.

The goal of exception handling is to never allow the application to abort
with a system error. Your application should handle all expected and unexpected exceptions.

In the case of unexpected exceptions, handle the exception by logging exception details to a file or some other source so that you can more quickly determine the cause of the exception. Then you can display a user-friendly message to the user and terminate the application gracefully.

To catch every possible exception in a Windows Forms application, you need to do one of the following:

  • Ensure that every application entry point has a Try/Catch block to
    catch every possible exception.
    This is actually much harder than it sounds. Since your application
    is event-driven, every event is a possible entry point into your application code. So you would have to add a Try/Catch block to every
    event handler in your application.
  • Write code in the appropriate unhandled exception event.

This post focuses on the second option: writing code in an appropriate unhandled exception event. Implement a global exception handler in a Windows Forms application as follows.

In C#:

In C#, you can trap the ThreadException event.

  1. Select a Windows Application project in Solution Explorer.
     
  2. Open the generated Program.cs file by double-clicking on it.
     
  3. Add the following line of code to the top of the code file:

    using System.Threading;
     

  4. In the Main() method, add the following as the first line of the method:

    Application.ThreadException +=
        new ThreadExceptionEventHandler(Application_ThreadException);

     

  5. Add the following below the Main() method:

    static void Application_ThreadException(
            object sender, ThreadExceptionEventArgs e)
    {
        // Do logging or whatever here

  6.     Application.Exit();
    }

  7. Add code to handle the unhandled exception within the event
    handler.
    Any exception that is not handled anywhere else in the application is
    handled by the above code. Most commonly, this code should log the error and display a message to the user.

NOTE: This code does not really "handle" the error. It just provides a place to log the error, perform any clean up operations, and display a message to the user. Unless you exit the application as shown in the sample code above, the code will attempt to continue, but will most likely be in an invalid state.

NOTE: This code only handles unhandled exceptions from the main UI thread. If you create other threads, they will need their own exception handling.

In VB:

With VB, Windows applications provide application events. One of these application events is the UnhandledException event, which the application generates whenever an unhandled exception occurs. You can write code for this event to catch any exception not specifically handled by your application.

  1. Select a Windows Application project in Solution Explorer.
     
  2. Open the Project Designer for the project by right-clicking the
    project and selecting Properties from the context menu, OR select
    Project | Properties from the main menu bar, OR double-click on
    the My Project folder under the project.
     
    image
     
  3. Select the Application tab of the Project Designer if it is not
    already selected.
     
  4. Ensure that the Enable application framework checkbox is
    checked.
     
  5. Click the View Application Events button.
    An ApplicationEvents.vb code file is added to your project, if it does
    not already exist, and is opened. The generated code is as follows:
  6. Namespace My

        ‘ The following events are available for MyApplication:
        ‘
        ‘ Startup: Raised when the application starts, before the startup form is created.
        ‘ Shutdown: Raised after all application forms are closed.  This event is not raised if the application terminates abnormally.
        ‘ UnhandledException: Raised if the application encounters an unhandled exception.
        ‘ StartupNextInstance: Raised when launching a single-instance application and the application is already active.
        ‘ NetworkAvailabilityChanged: Raised when the network connection is connected or disconnected.
        Partial Friend Class MyApplication

        End Class

    End Namespace

  7. Select (My Application Events) from the Class Name dropdown
    at the top left of the Code Editor.
     
  8. Select UnhandledException from the Event drop-down at the
    top right of the Code Editor. The following event handler code lines are generated:
     
    Private Sub MyApplication_UnhandledException( _
                         ByVal sender As Object, ByVal e As _
    Microsoft.VisualBasic.ApplicationServices.UnhandledExceptionEventArgs) _
                          Handles Me.UnhandledException
  9. End Sub

  10. Add code to handle the unhandled exception within the event
    handler.
    Any exception that is not handled anywhere else in the application is
    handled by this code. Most commonly, this code should log the error and
    display a message to the user.

NOTE: The VB UnhandledException event never occurs when you are running
with the debugger. When you are running with the debugger, Visual Studio catches the error and assists you with debugging it. To test the code in this event, use the option to "Start Without Debugging".

By setting up a global exception handler, you can ensure that your application catches any unexpected exception and never displays an unfriendly message to your users.

(Based on an except from "Doing Objects in Visual Basic 2005".)

Enjoy!

10 Comments

  1.   Chris Madsen — September 3, 2009 @ 12:16 pm    Reply

    Thanks for the interesting article. I had never tried using Application Events because my app doesn’t start from a form, which is required. Finally (duh) I realized that a tiny dummy form that hands off to my Sub Main would do the trick. Your article gave me the push.

  2.   Amit — September 4, 2009 @ 12:36 am    Reply

    I have tried this thing before. I wanted to catch StackOverflowException. But this thing is not working for StackOverflowException. For all other exceptions, this mechanism is perfect.

  3.   Kevin S Gallagher — September 29, 2009 @ 8:33 am    Reply

    In my agency all .NET WinForm solutions have global unhandled exception handlers using this technique. Besides logging information to an XML log file developers have the option to send exceptions to a specially setup mailbox. The mailbox has rules setup to send known applications exceptions to sub folders which are monitored. The advantage here is that many times a developer will see a message; fix the issue before a user calls in the problem which in turn equates back to the customer as good customer service on our end. All our unhandled exception handling is housed in a separate DLL (includes a custom dialog which morphs between user and technician interface) which makes it easy for a developer to plug in this functionality Susan is talking about. Sometime in the near future I will be releasing the source code including demonstration projects used to test this code which has made several jumps in Frameworks with no changes other than improvements. Location will be under http://code.msdn.microsoft.com/kevininstructor

  4.   Rebeccacgm — February 8, 2010 @ 10:10 am    Reply

    great read. I would love to follow you on twitter. By the way, did you guys hear that some chinese hacker had busted twitter yesterday again.

  5.   John — September 1, 2010 @ 1:57 am    Reply

    Hi,

    I needed this. I have added the code to my C# application and included a link to this page.

    I came here via: http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/4717f5d2-eb94-4710-b7c7-cd35fcb92ecf

    Thanks.

  6.   Rowter — September 7, 2010 @ 5:10 pm    Reply

    Hi Deborah,
    I am getting these 2 errors when i followed the steps above.
    Error 7
    ‘Public Shared Event ThreadException(sender As Object, e As System.Threading.ThreadExceptionEventArgs)’ is an event, and cannot be called directly. Use a ‘RaiseEvent’ statement to raise an event.

    Error 8
    Delegate ‘System.Threading.ThreadExceptionEventHandler’ requires an ‘AddressOf’ expression or lambda expression as the only argument to its constructor.

  7.   DeborahK — September 9, 2010 @ 3:08 pm    Reply

    Hi Rowter –

    Did you follow the C# or the VB directions? Those look like VB messages by my VB code did not use ThreadException?

  8.   DeborahK — September 9, 2010 @ 3:09 pm    Reply

    Hi Amit –

    Yes, the StackOverFlowException won’t be caught by this code.

    See this link for more information:
    http://msdn.microsoft.com/en-us/library/system.stackoverflowexception.aspx

    Hope this helps.

  9.   Chris Barnes — December 10, 2010 @ 4:04 am    Reply

    Hi Deborah,

    Thanks for the post,

    I have a few queries if that’s ok:

    1) I have implemented the central exception handler as you have detailed above in my Winforms VB.NET 2010 application but is there any need to have the following type of handlers in addition:

    AppDomain.CurrentDomain.UnhandledException, AddressOf CurrentDomain_UnhandledException

    AddHandler Application.ThreadException, AddressOf UIThreadException

    2) I do not want my application to terminate within MyApplication_UnhandledException so I have added
    e.ExitApplication = False
    which works OK although I was wondering if you had any views on if this is safe (I have simulated some errors and the application carries on fine afterwards).

    3) I have a splash screen in my winforms app and have simulated an error in there but cannot seem to prevent the application from terminating with an unhandled exception type message displayed by the CLR.

    Thanks a lot,
    Chris

  10.   Asish N R — May 21, 2012 @ 6:10 am    Reply

    Thread Exception might not handle all the exceptions. To overcome this issue, u can use the following code in the program.cs

    AppDomain.CurrentDomain.UnhandledException+= new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
    //Write your Error logging code here.
    }

RSS feed for comments on this post. TrackBack URI

Leave a comment

© 2021 Deborah's Developer MindScape   Provided by WPMU DEV -The WordPress Experts   Hosted by Microsoft MVPs