Exceptions are inevitable, so they might as well look good. Just
MessageBox.Show(ex.ToString()) doesn't cut it for me. I prefer something that not only looks better than that, but also makes it easy for users
to report all the information about an exception.
This article presents the
ExceptionViewer class. Similar to Microsoft's
ExceptionMessageBox, it's designed for displaying an exception, its nested inner
exceptions, and all their properties (using reflection). The source code download is a Visual Studio 2008 solution.
For years, I used the
ExceptionMessageBox class contained in Microsoft.ExceptionMessageBox.dll to display my exceptions. However, I was never comfortable
redistributing that DLL with my applications. Also, users never seemed to realize they could access more details about the exceptions and copy those
details into emails and bug reports. Finally, I'm using WPF now and
ExceptionMessageBox just doesn't look like it's part of a WPF app.
ExceptionViewer class in this article address those issues. It's simply a WPF window class you can add directly to your application (not requiring
a separate DLL). The "Copy All To Clipboard" button is highly visible so users are more likely to use it.
Using the Code
To display an exception, just construct an instance and call
catch (Exception ex)
ExceptionViewer ev = new ExceptionViewer("An unexpected error occurred in the application.", ex, this);
The last parameter to the constructor is optional. It specifies the
Owner window. If specified,
ExceptionViewer will set its own
Style property to the
Owner.Style and set
Of course, you can override these properties before calling
The default title of the window is "Error - <ProductName>", where <ProductName> is taken from the
AssemblyProduct attribute of the
application (specified in ApplicationInfo.cs). You can change this by setting the static property
DefaultTitle, or setting the instance property
Another static property,
DefaultPaneBrush, specifies the
Brush used for backgrounds of the two panes. It is null by default.
The first screen shot (at the top of the article) is how the window first appears to the user. There's a splitter between the two panes, positioned so all of
the left pane's content is visible without scrolling. The "All Messages" node is selected, which displays whatever header message is passed to the constructor in bold,
followed by the "outer" exception message, it's
InnerException message, and so on.
The following screen shot is how it looks when one of the exceptions is selected and "Wrap text" is unchecked. All of the exception's properties are displayed in the right pane, using the
exception's type as the header. Note that the key/value pairs of the
Data property, if any, are enumerated.
You can also expand an exception in the tree and view each property individually.
The "Copy All To Clipboard" button copies all of the information including the "header" message to the clipboard. Both Rich Text and Plain Text formats are placed
on the clipboard so the "best" format is used when pasting.
Mark Lauritsen has been a software developer since 1983, starting at IBM and using a variety of languages including PL/1, Pascal, REXX, Ada, C/C++ and C#. Mark currently works at a midstream energy company developing Windows services and desktop applications in C#.