Microsoft Exception MessageBox - Nice little gem

If you're developing WinForm applications, generally at some point in the project you develop an Exception Dialog box that provides a user friendly interface for error messages.  Usually, it's a generic box that displays parts of the exception stack and perhaps a way to log or allow users to initiate some other action such as proceeding, ignoring, or even reporting the error.  Usually the solution hooks in as the Application or AppDomain unhandled exception handler at startup. Thing is, I don't see much re-use between projects with what should be a re-usable component.

Microsoft Exception Message Box

The other day I was working with some of the downloads included in the Feature Pack for Microsoft SQL Server 2005 - April 2006 and I noticed in that pack an item called Microsoft Exception Message Box.  Here's the text for that download from the Feature Pack page:

The exception message box is a programmatic interface that you can use in your applications for any tasks for which MessageBox may be used. The exception message box is a supported managed assembly designed to elegantly handle managed code exceptions. It provides significantly more control over the messaging experience and gives your users the options to save error message content for later reference and to get help on messages.

More investigation, on the Microsoft MSDN website under Deploying an Exception Message Box Application the following statement appears:

The exception message box is installed by Microsoft SQL Server 2005 and is supported for use in your custom Windows applications to improve exception handling. In SQL Server 2005 SP1 and later releases, the exception message box is also provided as a redistributable installation program that you can distribute and deploy with your application.

It goes on to state:

  • You must include the exception message box redistributable package (SQLServer2005_EMB.msi) in your application setup.
  • Exception message box resources are installed in the global assembly cache (GAC).
  • The redistributable package is available in all supported SQL Server 2005 languages.
  • The exception message box installation does not appear in Add or Remove Programs. You should plan to uninstall the exception message box when your application is uninstalled.

What does this mean?  Well, Microsoft has granted us a license to use and redistribute this Assembly with our own applications as long as we follow the installation rules in the list above.

Sample Solution Files

Sample Solution

So, what does this thing do?

Before we proceed, some background on using the Assembly (Microsoft.ExceptionMessageBox.dll) in your solution.  First you'll need to establish a reference to the assembly.  Although it's installed in the GAC, if you attempt to add a reference in Visual Studio 2005 (this thing is .NET 2.0 Only), it doesn't show up in the Visual Studio .NET Reference Tab[1].  So, you just need to click the Browse Tab and navigate over to the C:\Program Files\Microsoft SQL Server\90\SDK directory.

Once you got the reference set, then you have access to the Namespace types in Microsoft.SqlServer.MessageBox.  There's a good set of steps located on MSDN How to: Program Exception Message Box.

The following set of examples are taken right from MSDN, but there's also shots of the actual MessageBox UI, which is absent on MSDN. So, let's take a look at some of the basic features.

The sample application with this article is located here: Sample Solution.  And a screen shot of the UI is shown below:

Simple OK

The basic ExceptionMessageBox is fairly basic dialog.  Additionally, the code is straightforward.

try
{
    // Do something that may generate an exception.
    throw new ApplicationException("An error has occurred");
}
catch (ApplicationException ex)
{
    // Define a new top-level error message.
    string str = "The action failed.";

    // Add the new top-level message to the handled exception.
    ApplicationException exTop = new ApplicationException(str, ex);
    exTop.Source = this.Text;

    // Show an exception message box with an OK button (the default).
    ExceptionMessageBox box = new ExceptionMessageBox(exTop);
    box.Show(this);
}

What that provides is a simple dialog, but as you'll see there's some additional features, even in the basic ExceptionMessageBox that are quite useful.  Here's the initial Dialog:

What you should notice is the two icons in the lower left.  The first allows copying of the contents of the message box to the user clipboard.  May seem novel, but some background - any windows message box if you do a Ctrl+C you can capture the text of the message box to the clipboard.  What the ExceptionMessageBox does is make the capability explicit and clickable. 

The second icon is a Advanced details button.  If you click that, you get the following:

Hopefully you can see that there's room for additional information that's potentially usable to anyone doing troubleshooting on your application.  As you'll see soon, you can expand this information even further by leveraging a new feature in .NET 2.0's System.Exception class.

Yes / No

This example provides a simple way of replacing a Dialog box and trapping the DialogResult for conditional processing.

// Define the message and caption to display.
string str = "Are you sure you want to delete file 'c:\\somefile.txt'?";
string caption = "Confirm File Deletion";

// Show the exception message box with Yes and No buttons.
ExceptionMessageBox box = new ExceptionMessageBox(str,
    caption, ExceptionMessageBoxButtons.YesNo,
    ExceptionMessageBoxSymbol.Question,
    ExceptionMessageBoxDefaultButton.Button2);

if (DialogResult.Yes == box.Show(this))
{
    // Delete the file.
}

Here the Yes / No option produces the following giving you conditional based processing:

Custom Buttons

Custom Buttons allow you to control the text on up to 5 buttons (Button1 - Button5) in addition to a None option.  Again, useful for conditional processing and providing text beyond the normal Abort, Retry, Ignore options.

try
{
    // Do something that may cause an exception.
    throw new ApplicationException("An error has occured");
}
catch (ApplicationException ex)
{
    string str = "Action failed. What do you want to do?";
    ApplicationException exTop = new ApplicationException(str, ex);
    exTop.Source = this.Text;

    // Show the exception message box with three custom buttons.
    ExceptionMessageBox box = new ExceptionMessageBox(exTop);

    // Set the names of the three custom buttons.
    box.SetButtonText("Skip", "Retry", "Stop Processing");

    // Set the Retry button as the default.
    box.DefaultButton = ExceptionMessageBoxDefaultButton.Button2;
    box.Symbol = ExceptionMessageBoxSymbol.Question;
    box.Buttons = ExceptionMessageBoxButtons.Custom;

    box.Show(this);

    // Do something, depending on the button that the user clicks.
    switch (box.CustomDialogResult)
    {
        case ExceptionMessageBoxDialogResult.Button1:
            // Skip action
            break;
        case ExceptionMessageBoxDialogResult.Button2:
            // Retry action
            break;
        case ExceptionMessageBoxDialogResult.Button3:
            // Stop processing action
            break;
    }
}

This is the UI with Custom Buttons

Exception Additional Data

.NET 2.0 added a new member to the System.Exception base class.  This member is a collection that implements IDictionairy - giving you a collection of key / value pairs that you can add additional state and condition information to an Exception that might be useful for Exception handlers or in our situation additional diagnostic information for the ExceptionMessageBox.

In the following code, again taken direct from MSDN, the ApplicationException's Data member is populated with 3 additional bits of information.

try
{
    // Do something that you don't expect to generate an exception.
    throw new ApplicationException("Failed to connect to the server.");
}
catch (ApplicationException ex)
{
    string str = "An unexpected error occurred. Please call Helpdesk.";
    ApplicationException exTop = new ApplicationException(str, ex);
    exTop.Source = this.Text;

    // Information in the Data property of an exception that has a name
    // beginning with "HelpLink.Advanced" is shown when the user
    // clicks the Advanced Information button of the exception message
    // box dialog box.
    exTop.Data.Add("AdvancedInformation.FileName", "application.dll");
    exTop.Data.Add("AdvancedInformation.FilePosition", "line 355");
    exTop.Data.Add("AdvancedInformation.UserContext", "single user mode");

    // Show the exception message box with additional information that 
    // is helpful when a user calls technical support.
    ExceptionMessageBox box = new ExceptionMessageBox(exTop);

    box.Show(this);
}

This results in additional information if you click on the Advanced Details button.

Here, in the red circle, you can see the additional strings added to the Data collection for the Exception type.  The ExceptionMessageBox has enumerated through the collection and displayed the ToString() for each item.

Summary

While many teams will develop their own Exception Message box and handling process, one thing to consider is whether the one provided here can meet the needs and save you a little time.  Certainly there are limitations to what you can do with this Assembly.  This article has only scratched the surface of what's possible.

Some features not shown here allow trapping of events such as OnCopyToClipboard along with additional property level control over the appearance and behavior.

So, I recommend that you take a look at what Microsoft has to offer here before coding up your own Exception Message box.  Least you can do is abstract and wrap today, and replace as needed in the future.

About

Shawn Cicoria is a Consultant with Avanade (www.Avanade.com) the leading Systems Integration Consultancy focused on the Microsoft Platform. Shawn is also a MCT training instructor with SetFocus (www.Setfocus.com) located in Parsippany NJ. Focused on distributed technologies such as COM[+], J2EE, and for the past 5 years .NET, SOAP, BizTalk, and Database technologies -- and now WinFX..

 

[1] The registry key HKLM\SOFTWARE\Microsoft\.NETFramework\AssemblyFolders controls what .NET Assemblies show up in the Visual Studio 2005 Add Reference .NET Tab.

Print | posted on Tuesday, May 9, 2006 12:03 PM

Comments on this post

# re: Microsoft Exception MessageBox - Nice little gem

Requesting Gravatar...
Nice!

Thanks for pointing it out...
Left by Greg on May 09, 2006 1:09 PM

# re: Microsoft Exception MessageBox - Nice little gem

Requesting Gravatar...
Great explaination...I will be using this
Left by Tim Hibbard on May 09, 2006 3:16 PM

# L'ExceptionMessageBox de SQL Server Management Studio utilisable dans nos applications ?

Requesting Gravatar...
J'avais bien entendu remarquer cette boite d'affichage avancée (qui est donc distribuée avec les produits...
Left by CoqBlog on Jul 21, 2006 7:04 AM
Comments have been closed on this topic.