Abstract
This article discusses structured exception handling (SEH), a service
built into the core of .NET and available to all languages supported by it.
Since the infrastructure for this service is built-in, there is very little
code required to take full advantage of these features.
As errors and unexpected events are a fact of life, one of the hallmarks of
professional programming is the implementation of exception handling code, that
is, code that ensures that an error in the execution gets identified and trapped
at its source, so that the application can:
- Continue running
- Provide helpful information about the source of
the error
- Ensure that the operating system is not brought
down
Historically, to write this kind of code meant that the programmer had to do
a lot of work, which in turn, meant that it did not get done because of the
deadlines that most programmers are up against.
Before .NET, when exception code was implemented, the most common method followed
was for a failed function to notify its caller there was a problem by returning
a non-standard value. The programmer would then have to write custom code to
check for this return value in order to trap the error.
The problem in this scenario, however, was that different functions return
different result codes, making it confusing and very time-consuming to tailor
the exception handling code for to the function being handled. Also, exceptions
returned only failure information and not much else to interpret the cause of
the exception.
As technology has developed, different programming languages have presented
a variety of different mechanisms for building exception handling code. Of the
pre-.NET languages, C++ and Java both supported SEH. The hallmark of SEH is
that an error object is employed to carry information about a failure while
a handler block in code to deals with that object. However, like most features
of any pre-.NET language, the feature only worked within that particular language,
and was therefore limited when building a robust and distributed application.
The Promise of .NET
Two of the key promises of .NET are to provide a number of services to the
developer that make the development process simpler, while minimizing the amount
of code that needs to be written.
The Common Language Runtime (CLR) - that part of .NET that manages the execution
of code - is where SEH is implemented. As a result, it is available to any .NET
language, and due to .NET's inherent cross-language capabilities, can support
this functionality equally as well in a scenario where several languages are
used to implement an application.
To use this feature, the programmer simply adds an exception handling block
to any operation which may fail. In Visual Basic.NET, the keywords Try
and Catch are used to demarcate these exception
handling blocks (in C#, try and catch
are used - note case sensitivity).
The following diagram shows how the CLR supports SEH when code is being executed
by it:

How It Works - Just Like Baseball!
In step one of the diagram above, when the CLR, .NET's managed program execution
runtime encounters a Try block, it automatically
takes care of step two and writes an exception handler to the call stack - so
you don't have to! In step three, the CLR calls the function in the Try
block and in step four, when it encounters an exception, it does what in .NET
parlance is known as throwing an exception. In step five, the CLR looks
back up the stack to find the exception handler that will provide the trace
back to the caller. In step six, the CLR tears down the stack and in step 7,
passes the trace information, along with control, back to the Catch
block of the executing code.
Any code can throw an exception by using the keyword Throw.
To do this, simply create a new object of type System.Exception.
Try, Catch,
and Throw - that's pretty much all that is needed
to know in order to work with structured exception handling in .NET.
Except - Finally
There's one more thing - Finally. The result
of throwing an exception is that the call stack is torn down. Any expensive
resources being used in the code that threw the exception will not be finalized
when the stack is torn down. For this purpose, the Visual Basic.NET keyword
Finally exists.
Code in a Finally block is executed as the
stack is torn down, so finalization code can be placed there. It is therefore
very is common to see Try-Catch-Finally
blocks in .NET SEH code.
Throw Your Own
Another important design point regarding SEH in .NET is that different types
of exceptions can be thrown to indicate different types of application issues.
The .NET Framework provides a base class, System.Exception,
from which it is possible to inherit and add additional properties and methods
which might better explain the exception to the catcher of the exception. The
following diagram shows the hierarchy of this base class as implemented in Beta2
of the .NET Framework:

The System namespace in the .NET Framework
defines two classes that inherit from System.Exception:
- System.ApplicationException:
This class is designed for implementing errors occurring within an application.
It is thrown by the application, not the CLR.
- System.SystemException:
This is the base class for predefined exceptions in the System
namespace. The most severe exceptions-those thrown by the runtime or in non-recoverable
conditions-include ExecutionEngineException
and StackOverflowException. It is not recommended
that you catch SystemExceptions, nor is it
good programming practice to throw SystemException
in your application. A SystemException is
always thrown by the CLR and this class should not be used to create custom
exceptions.
These two classes form the basis for most other runtime exceptions. Other exceptions
that derive directly from System.Exception include
IOException, WebException,
and XmlException.
Catching Different Balls
Adding even more power and flexibility to SEH in .NET is the ability to use
multiple catch statements in the Try/Catch
block in order to handle different exceptions that could be thrown. The order
of Catch statements is important. Catch
blocks targeted to specific exceptions must be placed before a general exception
catch block, or the compiler will issue an error. The runtime determined which
Catch block to execute by matching the type
of the exception to the name of the exception specified in the Catch
block. If there is no specific Catch block,
then the exception is caught by a general Catch
block, if one exists.
Outside the CLR
One last important point needs to be discussed before going into the code
example. It is the fact that .NET can work with code that is outside of the
CLR, such as COM components and COM+ services. This is known as interoperability
with unmanaged code.
The SEH model implemented in .NET can support exceptions that occur when unmanaged
code is involved as well! Interoperation exceptions derive from SystemException
and are further extended by ExternalException.
Also, Win32Exception, which reports back errors
from any calls made to the Win32API and SEHException,
which reports back errors from calls made to external code implementing their
own SEH, also derive from ExternalException.
Let's Play Ball!
I have provided an application with this code that demonstrates the use of
both SystemExceptions and ApplicationExceptions.
What follows is a review of the key points.
Application Structure
If the application is opened in Visual Studio.NET and look in the Solution
Explorer, the following files will be seen:

The application I have provided is written in two logical projects - one containing
an SEH component and the other a client component. This is a standard way for
.NET applications to be written, enabling a component to be reused by a variety
of clients. I will first look at the SEH component.
SEH Component
The implementation of the SEH component is found in the file Class1.vb
under the SEHComponent project tree. The file starts by declaring two
distinct ApplicationExceptions that will be
used for this application:
'Class Declarations
Dim DBException As New
ApplicationException("An application exception as been thrown. This
is caused by a failure to connect to the backend database this application
depends on.")
Dim SECException As New
ApplicationException("An application exception as been thrown. This
is caused by security authentication failure.") |
The idea here is that there can be many exceptions for many reasons. Good SEH
code design process will review the possibilities and document all known exceptions.
The next section shows a function and how an exception is thrown:
Public Function Function1()
As String
'Set exception source properties to identify
current exception source
DBException.Source = "Function1"
SECException.Source = "Function1"
Try
'Code to run would go here
Throw DBException
'Code to throw app SECException
would go here
Finally
MessageBox.Show("Any expensive resources are
released here." & _
"Try block will now terminate.",
_
"Finally Block", MessageBoxButtons.OK,
_
MessageBoxIcon.Information)
End Try
End Function |
Here, properties of the custom exceptions are set and in this function a DBExpection
is thrown. Following this, the Finally block
would release the resources the function had locked.
The next function, Function2(), does the same
thing, but for SECException in order to simulate
an SECException.
Function3() does the same thing again, except
this function will throw a SystemException as
it attempts to perform an illegal mathematical operation. Note in the code block
for Function3() that there are stubs for the
other exceptions - in real life, all three functions would be one and the conditions
for throwing the specific exceptions would be clearly defined.
This code shows that throwing exceptions in .NET is very easy to do - now on
to catching
Client Component
The implementation of the client component uses a Windows Form, but this could
just as easily be a Web Form:

First, a form with three button to trigger the three different exceptions is
created. Then, the code behind this form triggers the events and catches the
exceptions.
Add a Reference
Before the SEHComponent can be used by the client, it is necessary
to import a reference to it as follows:
1. Right-click on the References icon in the solution explorer and select Add
Reference :

2. A dialogue box will come up - select the "Projects" tab and then
select the SEHComponent:

3. Click OK
The reference will now appear as part of the Client Component references.
Catching an Exception
I will look first at the code that handles the first button:
Private Sub
btnError1_Click(ByVal sender As
System.Object, ByVal e As
System.EventArgs) Handles btnError1.Click
Dim ec As
New SEHComponent.Class1() |
The first thing it does is to instantiate its own SEHComponent
so that it can call SEHComponent methods. The
next step is to attempt to do something in a Try
block and Catch specific exception types, as
follows:
Try
ec.Function1()
Catch x As ApplicationException
MessageBox.Show("Message = " + _
x.Message + " " + "Source = "
+ _
x.Source + " " + "Stack Trace = "
+ _
x.StackTrace, "Application Error", _
MessageBoxButtons.OK, _
MessageBoxIcon.Hand)
Catch x As Exception
MessageBox.Show("Message = " + _
x.Message + " " + "Source = "
+ _
x.Source + " " + "Stack Trace = "
+ _
x.StackTrace, ".NET System Error", _
MessageBoxButtons.OK, _
MessageBoxIcon.Stop)
End Try |
Note that the code first tries to catch a specific ApplicationException
and then a general Exception.
The other two button handlers do exactly the same thing - they just call different
functions to simulate different errors.
The Results, Please!
Here is what happens when the DB Exception button is clicked:

The previous dialog is notification that the finally block in the SEHComponent
firing and releasing the resources.

This message then follows - the Exception object
has passed back all of this information, which can be used any way the programmer
sees fit.
Here is what happens when the System Error button is clicked:

The previous dialog is notification that the finally block in the SEHComponent
firing and releasing the resources.

And this message is the SystemException being
passed back.
Conclusion
SEH in .NET is very straightforward and consistent throughout .NET. This implementation
supports all .NET languages, unmanaged code & interoperability and is fully
extensible. With features like these, there is no longer any excuse not to implement
fully featured SEH in the components and application programmers develop. Doing
so will make working with and developing from multiple components manageable.
I would also like to include here for your reference a link to best
practices for SEH as included in the .NET SDK.
I hope you have enjoyed this article and learned a lot - now go write some
great code!