Code Focused

It's Safe to Handle Unhandled Visual Basic and C# Exceptions

Pile on the exceptions, and .NET will have your back with the tools it provides at your disposal.

Unhandled exceptions are a bit of a misnomer. In .NET, every exception is handled. By the time you access the specifics of an error in your Try-Catch block, the Framework has already analyzed the problem, built a structure to contain its details, examined the stack trace, and used reflection to pinpoint the location of the error, among other mundane tasks. In short, when errors occur, .NET serves them up to your code in a neatly packaged, highly examinable data block.

As busy as .NET is in dealing with exceptions, it is still a gentleman. Even if you choose to ignore thrown events when they occur, the Framework gives you one more chance, through the medium of unhandled exception processing.

Visual Basic makes it especially easy to intercept and process these nearly lost exceptions through its Windows Application Framework. When supported by a specific project type, the framework enables a handful of programmer-friendly events, including an UnhandledException event that's precisely what you're looking for. To access the event, open the Application tab of the Project Properties panel in your project, ensure that the Enable Application Framework checkbox is selected and, finally, click on the View Application Events button.

This button click adds the ApplicationEvents.vb file to your project. Using the event dropdown controls along the top of the code editor, access the UnhandledException event. The file now contains this exciting code:

Imports Microsoft.VisualBasic.ApplicationServices
Namespace My
  Partial Friend Class MyApplication
    Private Sub MyApplication_UnhandledException(
      sender As Object, e As UnhandledExceptionEventArgs) _
      Handles Me.UnhandledException

    End Sub
  End Class
End Namespace

After you add this handler to your project, any exception not fully processed within a Catch block arrives here, ready for last-second analysis. The e.Exception parameter field presents the full details on the exception in question. That's nice and all, but if you still choose to do nothing in this method, your program will crash. That's because the default behavior after moving through the UnhandledException handler is to exit the program. If you want your user to continue working without complaint, set the ExitApplication flag to False within the handler:

e.ExitApplication = False

C# lacks the application framework, so unhandled exception processing is configured when your program first begins, as part of the Main method. There are a few variations to the setup, depending on whether you want a Windows Forms or non-Windows Forms focus. But as with Visual Basic, all of the options use an event handler to capture and process the previously unhandled error. (These variations can be used in Visual Basic, as well, by accessing the same classes and events utilized in C#.)

In Windows Forms applications, your code should monitor the UI-thread-specific Application.ThreadException event. First, add the handler to the class that contains your Main method, or to some other convenient and accessible part of the code:

// Assumes: using System.Threading;
private static void UIGlobalErrorHandler(
  object sender, ThreadExceptionEventArgs e)
{
  // ----- e.Exception exposes the error object.
}

Then back in your Main method, add code to link up the event to the handler:

// Assumes: using System.Threading;
Application.ThreadException +=
  new ThreadExceptionEventHandler(UIGlobalErrorHandler);
Application.SetUnhandledExceptionMode(
  UnhandledExceptionMode.CatchException);

For project types other than Windows Forms -- or to deal with certain types of non-UI exceptions within Windows Forms applications -- your handler attaches to an event at the application-domain level. The event handler looks a lot like the UI version, but with a different data type for the passed-in exception container:

private static void GlobalErrorHandler(
  object sender, UnhandledExceptionEventArgs args) 
{
  // ----- e.ExceptionObject exposes the error object.
}

Activate the event using a normal event-connection syntax in your Main method:

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

Unlike the Visual Basic version, these unhandled exception handlers do not terminate easily. Normally, the program will continue to run even after error processing. To exit the program abruptly, you need to call one of the framework termination methods, such as Application.Exit.

As a programmer, the choice to deal with errors or let them pile up on the user's screen is entirely up to you. But with the .NET Framework giving you so many tools to manage errors when and after they occur, it's practically begging you to live up to your exception-processing expectations.

About the Author

Tim Patrick has spent more than thirty years as a software architect and developer. His two most recent books on .NET development -- Start-to-Finish Visual C# 2015, and Start-to-Finish Visual Basic 2015 -- are available from http://owanipress.com. He blogs regularly at http://wellreadman.com.

comments powered by Disqus

Featured

  • Compare New GitHub Copilot Free Plan for Visual Studio/VS Code to Paid Plans

    The free plan restricts the number of completions, chat requests and access to AI models, being suitable for occasional users and small projects.

  • Diving Deep into .NET MAUI

    Ever since someone figured out that fiddling bits results in source code, developers have sought one codebase for all types of apps on all platforms, with Microsoft's latest attempt to further that effort being .NET MAUI.

  • Copilot AI Boosts Abound in New VS Code v1.96

    Microsoft improved on its new "Copilot Edit" functionality in the latest release of Visual Studio Code, v1.96, its open-source based code editor that has become the most popular in the world according to many surveys.

  • AdaBoost Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the AdaBoost.R2 algorithm for regression problems (where the goal is to predict a single numeric value). The implementation follows the original source research paper closely, so you can use it as a guide for customization for specific scenarios.

  • Versioning and Documenting ASP.NET Core Services

    Building an API with ASP.NET Core is only half the job. If your API is going to live more than one release cycle, you're going to need to version it. If you have other people building clients for it, you're going to need to document it.

Subscribe on YouTube