Error Handling in Visual Basic .NET

 

Ken Getz
MCW Technologies

February 2002

Summary: Discusses how error handling differs between Visual Basic .NET and Visual Basic 6.0. Main topics include Try/Catch blocks, Exception objects, procedure callers, and how to create your own Exception classes. (17 printed pages)

Objectives

  • Compare error handling in Microsoft® Visual Basic® .NET to that found in Visual Basic 6.0
  • Learn to use Try/Catch blocks to handle runtime errors
  • Use Exception objects to determine what error has occurred
  • Throw exceptions back to procedure callers
  • Create your own Exception classes

Contents

Getting Started with Structured Exception Handling
Adding Error Handling
Working with Specific Exceptions
Raising Errors
Running Code Unconditionally
Creating Exception Classes
Summary
About the Author
About Informant Communications Group

Getting Started with Structured Exception Handling

The .NET Framework provides structured exception handling, using the Try, Catch, Finally, and Throw keywords in Visual Basic .NET. This type of error handling has been available, in some fashion, in C++ for a number of years. With the release of the .NET common language runtime, this type of error handling is available to all the .NET languages including, Visual Basic .NET.

Where We've Been

Although Visual Basic has supported its own mechanism for handling errors for as long as the "Visual" has been attached to the product's name, the techniques available to Visual Basic developers have seemed incomplete. There are several issues surrounding error handling in Visual Basic (see Listing 1 below) that have caused many complaints among Visual Basic developers, both experienced and novice:

  • Visual Basic 6.0 requires you to jump around within procedures, in order to handle errors. The On Error Goto, Resume, and Resume Next statements all involve jumping forwards or backwards in code. The standard Visual Basic 6.0 error-handling techniques involve at least one jump, and often more, within a procedure (one forward to the error handling block, and a second back to a common procedure exit point.)
  • If you follow good programming practices in Visual Basic 6.0, including ensuring that your procedures have only a single exit point, the most convenient place to put that exit point is in the middle of procedures (before the error-handling block), making it easy to forget the important Exit Sub or Exit Function.
  • There is no way to push and pop error handlers in Visual Basic 6.0. If you want to preserve the current error trap, set up a different one, and then return back to the first one. You must remember to include the correct On Error Goto… statement every time you want to change handlers.
  • Visual Basic 6.0 includes only a single Err object. If an error occurs, and you don't handle that error immediately, you may have permanently lost the error information before you get a chance to handle the error.
  • The Visual Basic 6.0 documentation includes almost no coverage of the types of errors (that is, the error numbers) you might receive because of an action you've taken in your code. Your only recourse is to experiment, see what error numbers you can generate by triggering errors while testing, and trap those specific errors in your code.

Listing 1. Error handling in Visual Basic 6.0 required at least one jump, and often more.

Sub TestVB6()
    On Error GoTo HandleErrors
    
    ' Do something in here that
    ' might raise an error.
    
ExitHere:
    ' Perform cleanup code here.
    ' Disregard errors in this
    ' cleanup code.
    On Error Resume Next
    ' Perform cleanup code.
    Exit Sub
    
HandleErrors:
    Select Case Err.Number
        ' Add cases for each
        ' error number you want to trap.
        Case Else
            ' Add "last-ditch" error handler.
            MsgBox "Error: " & Err.Description
    End Select
    Resume ExitHere
End Sub

In addition, although Visual Basic developers were perfectly capable of using the Err.Raise method to raise errors back to calling procedures, this technique never became a standard. Many developers creating code that is called by others simply return an error value to indicate success or failure, instead of raising an error on failure. Because it's possible (and easy) to simply disregard error values returned from procedures you call, in too many cases, code that fails for any reason at runtime never raises the appropriate errors back to its callers.

Where We Are

With the addition of structured exception handling, it's easier for developers to manage error notification, raise errors, and determine the cause of a runtime error. Structured exception handling provides several features that offer more flexible error handling than in previous versions of Visual Basic:

  • Error handling in .NET is based on the Exception class, which contains information about not only the current error, but a linked list of errors that may have triggered the current error.
  • You can inherit from the Exception class, creating your own exceptions that have the same functionality as the base class, or you can create extended functionality as necessary. Because your code can trap for specific exceptions, creating your own Exception class gives you a lot of flexibility.
  • Because every class in the .NET framework throws exceptions when it encounters runtime errors, developers will get in the habit of trapping for exceptions and handling them. This makes it more likely that exceptions you throw from within your components will be successfully handled.
  • You can nest Try/Catch blocks within the Try, Catch, or Finally blocks. This gives developers the capability of managing exception handling to any level of granularity that they require.

Listing 2 shows the layout of a simple exception handler in Visual Basic .NET. The following sections describe, in detail, how to use each of the keywords shown in Listing 2, and how to use the Exception class in tracking and raising errors.

Listing 2. Error handling in Visual Basic .NET doesn't require jumping around.

Sub TestVBNET()
  Try
    ' Do something in here that
    ' might raise an error.
  Catch
    ' Handle exceptions that occur within
    ' the Try block, here.
  Finally
    ' Perform cleanup code in here.
  End Try
End Sub

**Tip   **You can mix old-style Visual Basic 6.0 error handling with .NET structured exception handling in the same project, but not within the same procedure. On Error and Try can't exist within the same procedure.

Raising an Error

The next several examples use the same basic premise—your goal is to open a file, retrieve its length, and then close the file. Each example uses this code to do its job, retrieving the file name from a text box on the sample form, txtFileName:

Dim lngSize As Long    ' Length is 64-bit number.
Dim s As FileStream

s = File.Open(txtFileName.Text, FileMode.Open)
lngSize = s.Length
s.Close()

Of course, it's possible (for many reasons) that the code might fail. For example, the code will raise an exception if:

  • The file isn't found.
  • The path doesn't exist.
  • The drive containing the file isn't ready (perhaps you've requested the size of a file on a floppy drive that doesn't contain media).
  • You don't have permissions to access the file or folder.
  • You've specified an invalid file name.

The list could go on and on. The following few examples explore some variation of this code in order to demonstrate features of structured exception handling.

Adding Error Handling

The following sections work through a series of examples, adding increasingly complex error handling features to the sample code you've seen already. Starting with the scenario in which you've added no exception handling code at all, these examples introduce the concepts of trapping and identifying exceptions in Visual Basic .NET.

The sample application corresponding to this material, ErrorHandling.sln, includes a form, frmErrors, that allows you to try out the various techniques described here (see Figure 1). For each case, try entering the path to a file that doesn't exist, or a drive that doesn't exist, or a drive that doesn't contain any media, or any other path that might trigger a file system error.

Figure 1. Use this sample form to demonstrate all the different features discussed here.

The Base Case—No Error Handling at All

What happens if your code includes no exception handling at all? In that case, any errors that occur at runtime bubble back up to the .NET runtime, and the runtime will greet your users with a confusing, and potentially dangerous, dialog box, shown in Figure 2. In order to avoid this dialog box, should a runtime error occur, you'll need to add exception handling to at least your top-level procedures, and to lower-level procedures as necessary.

Figure 2. The inclusion of a Continue button makes the .NET default error handler somewhat dangerous. In addition, the details aren't something you want your user to see.

**Tip   **Just as in Visual Basic 6.0, if you don't add exception handling to a procedure, and an error occurs within that procedure, the .NET runtime will pop the current procedure off the call stack, and will return to the previous procedure. If that procedure includes error handling, the runtime will use that code. If not, the runtime will continue to pop procedures off the stack until it backs out to a procedure that does include error handling. If no procedures include error handling, all the way back to the first-called procedure, the .NET runtime handles the error itself, as in Figure 2.

Adding a Simple Try/Catch/End Try Block

In order to gracefully handle runtime errors, add a Try/Catch/End Try block around any code that you want to protect. If a runtime error occurs in the code within the Try block, execution will immediately continue with the code within the Catch block:

Try
  s = File.Open(txtFileName.Text, FileMode.Open)
  lngSize = s.Length
  s.Close()
Catch
  MessageBox.Show("Error occurred!")
End Try

When this code runs, rather than the application displaying an alert and halting, you'll see a simple "Error occurred" alert, and the application can continue. To test this yourself, choose the Simple Catch option in the Error Handling combo box on the sample form.

**Tip   **If you add a Try/Catch/End Try block to your procedure, you'll need to include at least a single Catch block (you'll find more information on including multiple Catch blocks later). If you want to disregard errors that occur, simply put nothing at all into the Catch block. This isn't a great idea, but it will quietly disregard any errors that occur.

Determining What Happened

Once a runtime error occurs, how can you determine what error it was, and how you might deal with the error? You can create a variable, declared using As Exception, to retrieve error information for you. The Exception class provides information about the runtime error, as shown in Table 1.

Member Description
HelpLink Link to the help file associated with this exception.
InnerException A reference to the inner exception—the exception that originally occurred, if this exception is based on a previous exception. Exceptions can be nested. That is, when a procedure throws an exception, it can nest another exception inside the exception it's raising, passing both exceptions out to the caller. The InnerException property gives access to the inner exception.
Message Error message text.
StackTrace The stack trace, as a single string, at the point the error occurred.
TargetSite The name of the method that raised the exception.
ToString Converts the exception name, description, and the current stack dump into a single string.
Message Returns a description of the error that occurred.

Table 1. Useful members of the Exception class

The Catch block includes the reference to the variable, like this:

Try
    ' Code that might trigger an exception.
Catch e As Exception
    ' Handle the exception, using e, in here.
End Try

You can also declare the Exception variable outside the Catch block:

Dim e As Exception
Try
    ' Code that might trigger an exception.
Catch e
    ' Handle the exception, using e, in here.
End Try

You might use code like this to trap an exception, and display text indicating the problem that has occurred:

' Simple Exception option on the sample form.
Private Sub SimpleException()
  Dim lngSize As Long
  Dim s As FileStream

  ' Display the entire contents of the Exception object.
  Try
    s = File.Open(txtFileName.Text, FileMode.Open)
    lngSize = s.Length
    s.Close()
  Catch e As Exception
    MessageBox.Show(e.ToString)
  End Try
End Sub

**Tip   **The name of the Exception object isn't important. The sample code uses e as the variable name, but that choice was arbitrary. If you find that name inconvenient in your own procedures, you may prefer to choose a different name.

If you simply want to display an error message indicating the particular error that you've trapped, you can use the Message property of the Exception class, like this:

' Which Exception option on the sample form.
Private Sub WhichException()
  Dim lngSize As Long
  Dim s As FileStream

  ' Now you can at least tell what went wrong!
  Try
    s = File.Open(txtFileName.Text, FileMode.Open)
    lngSize = s.Length
    s.Close()
  Catch e As Exception
    MessageBox.Show("Error occurred: " & e.Message)
  End Try
End Sub

So far, you've seen how to trap an exception when it occurs, and how to indicate to the user what went wrong. Most of the time you'll also need to be able to take distinct action depending on the specific error that occurred. In Visual Basic 6.0, this meant adding a Select Case block based on the active error number. In Visual Basic .NET, this involves adding additional Catch blocks for each error you'd like to trap individually. The next section digs into how you can add this functionality to your procedures.

Working with Specific Exceptions

The .NET Framework provides a significant number of specific exception classes, all inheriting from the base Exception class. In the .NET Framework documentation, you'll find tables listing all the possible exceptions that might occur when you call any method. For example, Figure 3, captured from the .NET Framework documentation, makes it easy to determine what might go wrong when calling the File.Open method.

Figure 3. .NET documentation lists all the exceptions that might occur when calling the File.Open method

Your procedures can include as many Catch blocks as necessary in order for you to handle individual exceptions differently. The following procedure, from the sample project, tests for several different exceptions, and handles each exception individually. To test this procedure, try a number of specific exceptions. For example, change the file name to be:

  • In a valid path, but select a file that doesn't exist.
  • On a drive that doesn't exist.
  • In a path that doesn't exist.
  • On a drive that isn't ready.
' Multiple Exceptions option on the sample form.
Private Sub MultipleExceptions()
  Dim lngSize As Long
  Dim s As FileStream

  Try
    s = File.Open(txtFileName.Text, FileMode.Open)
    lngSize = s.Length
    s.Close()
  Catch e As ArgumentException
    MessageBox.Show( _
     "You specified an invalid filename. " & _
     "Make sure you enter something besides spaces.")
  Catch e As FileNotFoundException
    MessageBox.Show( _
     "The file you specified can't be found. " & _
     "Please try again.")
  Catch e As ArgumentNullException
    MessageBox.Show("You passed in a Null argument.")
  Catch e As UnauthorizedAccessException
    MessageBox.Show( _
     "You specified a folder name, not a file name.")
  Catch e As DirectoryNotFoundException
    MessageBox.Show( _
     "You specified a folder that doesn't exist " & _
     "or can't be found.")
  Catch e As SecurityException
    MessageBox.Show( _
     "You don't have sufficient rights " & _
     "to open the selected file.")
  Catch e As IOException
    ' A generic exception handler, for any IO error
    ' that hasn't been caught yet. Here, it ought
    ' to just be that the drive isn't ready.
    MessageBox.Show( _
     "The drive you selected is not ready. " & _
     "Make sure the drive contains valid media.")
  Catch e As Exception
    MessageBox.Show("An unknown error occurred.")
  End Try
End Sub

Determining the Exception Hierarchy

Following any of the links in the Exceptions table shown in Figure 3 takes you to documentation on the individual Exception object. This documentation includes an inheritance hierarchy, as shown in Figure 4. You'll need to understand this hierarchy of objects when you add multiple Catch blocks.

Figure 4. The inheritance hierarchy allows you to determine the "is a" relationship for objects.

Using the Exception Inheritance Hierarchy

In the exception hierarchy shown in Figure 4, you can see that ArgumentNullException inherits from ArgumentException, which inherits from SystemException, which inherits from Exception. Each level in the hierarchy indicates an increasing level of specificity—that is, the lower you go, the more specific the exception.

Because each level inherits from the class defined above it, each lower level is an instance of the type specified above it. ArgumentNullException "is a(n)" ArgumentException, which "is a" SystemException, which "is a(n)" Exception. The "is a" appears in quotes here, because it's a meaningful operator—when you have multiple Catch blocks, those blocks match against the current exception using an "is a" rule. That is, when processing multiple Catch blocks, when the runtime first finds a match where the current exception meets the "is a" rule for the exception trapped by the Catch block, the runtime uses that Catch block to process the exception and doesn't look any further. In other words, the order of the Catch blocks is significant, based on this "is a" relationship. All exceptions inherit from the base Exception class, so you'll always want to include a Catch block handling the base Exception class last, if you include it at all.

Raising Errors

You may want to raise errors out of your procedures, indicating to callers that some exception has occurred. You might want to simply pass back a standard runtime exception provided by the .NET Framework, or you might want to create your own exception condition. In either case, you'll use the Throw keyword to raise the exception out of the current block.

Note The Throw keyword works in much the same manner as the Err.Raise method in Visual Basic 6.0.

Using the Throw Keyword

You can use the Throw keyword in two ways. You can:

  1. Throw the error that just occurred back out to the caller from within a Catch block:

    Catch e As Exception
      Throw
    
  2. Throw an error from within any code, including a Try block:

    Throw New FileNotFoundException()
    

    Note The first technique, throwing the exception that just occurred, only works from within a Catch block. The second technique, throwing a new error, works anywhere.

Searching for Handlers

When you throw an exception, the .NET runtime works its way up the procedure call stack, looking for an appropriate exception handler. (If you're in a Try block when you throw your exception, the runtime will use the local Catch blocks, if any, to handle the exception first.) As soon as the runtime finds a Catch block for the exception you've thrown, it executes the code it finds there. If it can't find any appropriate Catch block all the way up the call stack, the runtime handles the exception itself (as shown earlier in Figure 2).

Error Handling Options

You can determine which exceptions you want to handle, and which ones you want to raise back to your callers. When an exception occurs, your options include:

  • Do nothing at all. In this case, the .NET runtime will automatically raise the exception back out to the procedure that called your code.

  • Catch specific errors. In this case, exceptions you do handle won't be passed back out, but those you don't handle will be thrown back to the calling procedure.

  • Handle all errors. Add a "Catch e as Exception" block to your set of Catch blocks, and no error will ever pass through your exception handling unless you specifically throw an error yourself.

  • Throw errors. You have the option to throw any error back out to the caller, explicitly. Using the Throw statement you can raise the current error, or any other error, to the caller's exception handler.

    **Tip   **If you throw an exception using the Throw keyword, Visual Basic 6.0-style On Error Goto error handling can trap the error, as well. That is, the .NET runtime uses the same plumbing under the covers for all exceptions, whether you use the old or new error handling conventions.

Passing Error Information

If you want to intercept different exceptions and raise them all back out to the caller as a single exception type, Throw makes it easy. In the next example, the code catches all exceptions, and no matter what caused the exception, throws a FileNotFoundException object back to the caller. In some cases, like this one, the calling procedure may not care exactly what happened, or why the file couldn't be found. The caller may only care that the file wasn't available, and needs to discern that particular exception from other, different exceptions.

The Exception object constructor

The Exception object's constructor is overloaded in several ways. You can pass in no parameters (you'll get a generic Exception object, with default values for its properties); a string indicating the error message you want sent back to the caller; or a string and an Exception object, indicating the error message and the original exception that occurred (filling in the InnerException property of the exception you pass back to the caller). The example here uses the final constructor, passing back the inner exception.

You may also wish to make the original exception information available to the caller, in addition to the exception your code raises. In that case, you'll find that the constructor for the Exception class provides an overloaded version that allows you to specify the inner exception. That is, you can pass the exception object that originally raised the error. The caller can investigate this exception, if it needs to.

**Tip   **The InnerException property of an exception is itself an Exception object, and it may also have an InnerException property that isn't Nothing. Therefore, you may end up following a linked list of exceptions when you start digging into the InnerException property. You may need to continue retrieving the InnerException property repeatedly until the property returns Nothing, in order to dig through all the errors that may have occurred.

In the following example, the TestThrow procedure throws a FileNotFoundException back to its caller, no matter what error it receives. In addition, it fills in the exception's InnerException property with the original exception object. This example displays the fabricated error message, along with the text associated with the original exception:

' Throw Exception option on the sample form.
Private Sub ThrowException()
  Dim lngSize As Long
  Dim s As FileStream

  ' Catch an exception thrown by the called procedure.
  Try
    TestThrow()
  Catch e As FileNotFoundException    MessageBox.Show("Error occurred: " & e.Message)    ' Use e.InnerException to get to error    ' that triggered this one.    MessageBox.Show(e.InnerException.Message)
  End Try
End Sub

Private Sub TestThrow()
  Dim lngSize As Long
  Dim s As FileStream

  ' No matter what happens, throw back 
  ' a File Not Found exception.
  Try
    s = File.Open(txtFileName.Text, FileMode.Open)
    lngSize = s.Length
    s.Close()
  Catch e As Exception
    Throw (New FileNotFoundException( _      "Unable to open the specified file.", e))
  End Try
End Sub

Running Code Unconditionally

You may find that, in addition to code in the Try and Catch blocks, you want to add code that runs whether an error occurs, or not. You may need to release resources, close files, or handle other issues that need to take place under any circumstances. In order to run code unconditionally, you'll need to use the Finally block.

The Finally Block

To run code unconditionally, add a Finally block after any Catch blocks. The code in this block will run even if your code throws an exception, and even if you add an explicit Exit Function (or Exit Sub) statement within a Catch block. The code in the Finally block runs after the exception-handling code, but before control returns back to the calling procedure.

You may decide, for example, that your code needs to set the FileStream object variable to Nothing, whether or not any error occurs when working with the file. You can modify the procedure to look like this, calling the finalization code whether or not an error occurs:

' Test Finally option on the sample form.
Private Sub TestFinally()
  Dim lngSize As Long
  Dim s As FileStream

  Try
    s = File.Open(txtFileName.Text, FileMode.Open)
    lngSize = s.Length
    s.Close()
  Catch e As Exception
    MessageBox.Show(e.Message)
  Finally    ' Run this code no matter what happens.    s = Nothing
  End Try
End Sub

**Tip   **Although your Try/End Try block must contain either one or more Catch blocks, or a Finally block, it needn't contain both. That is, a Finally block without Catch blocks is fine. Why include a Finally block if you don't include a Catch block? If an exception occurs within your procedure, the .NET runtime will look for an appropriate exception handler, and that may mean it leaves your procedure (if there's no Catch block, this will certainly happen), looking up the call stack for that exception handler. If you want to run code before the runtime leaves your procedure, you need to include a Finally block. If, for example, you're working with an object that provides a Dispose method, and you want to make sure you call it before you leave your procedure, place that call to the Dispose method within a Finally block, whether or not you use a Catch block. That way, even if an error occurs, your Dispose method call will occur before the .NET Framework passes your exception back up to the calling procedure.

Creating Exception Classes

You may find that the .NET Framework doesn't supply you with an Exception class that meets your specific needs. For example, you might want to raise an exception, if the user selects a file that's larger than 100 bytes. Although this isn't generally considered to be an exception condition, it may be an error condition within your application.

To create your own exception class, follow these steps:

  1. Create a new class.

  2. Inherit from the ApplicationException base class.

    Note You can actually inherit from any class that itself inherits from the Exception class. For example, you may want to inherit from the IOException class, or the FileNotFoundException. Any of these will do as the base class for your own exception. The documentation suggests that you don't inherit directly from Exception, however.

  3. Provide your own New method (add appropriate overloads, as necessary). Call back to MyBase.New to include the call to the base class' constructor.

  4. Add any additional functionality that you need.

The FileTooLargeException Class

The sample project includes the following class definition (within the frmErrors.vb module), providing the definition for the FileTooLargeException:

Public Class FileTooLargeException
  Inherits ApplicationException
  Private mlngFileSize As Long

  Public Sub New(ByVal Message As String)
    MyBase.New(Message)
  End Sub

  Public Sub New(ByVal Message As String, _
   ByVal Inner As Exception)
    MyBase.New(Message, Inner)
  End Sub

  Public Sub New(ByVal Message As String, _   ByVal Inner As Exception, ByVal FileSize As Long)    MyBase.New(Message, Inner)    mlngFileSize = FileSize  End Sub  Public ReadOnly Property FileSize() As Long    Get      Return mlngFileSize    End Get  End Property
End Class

This class provides the standard Exception class properties (because it inherits from ApplicationException), but adds a new wrinkle—it adds a new constructor, which allows you to pass in the size of the file that triggered the exception. In addition, it provides a FileSize property, so your procedures' callers can determine the size of the file that triggered the exception.

The GetSize function, shown here, attempts to open a file. If the file you've requested is too large, GetSize throws a FileTooLargeException back to its caller, passing its own error message and the size of the file you requested:

Private Function GetSize( _
 ByVal strFileName As String) As Long
  Dim lngSize As Long
  Dim s As FileStream

  ' Return the file size. If it's larger than 100 bytes
  ' (an arbitrary size), throw a FileTooLargeException
  ' (a user-defined exception) to the caller.

  Try
    s = File.Open(txtFileName.Text, FileMode.Open)
    lngSize = s.Length
    s.Close()
    If lngSize > 100 Then
      ' Pass back the new exception. There's no
      ' inner exception to pass back, so pass Nothing.
      Throw (New FileTooLargeException( _       "The file you selected is too large.", _       Nothing, lngSize))
    End If
    Return lngSize
  Catch
    ' Throw the exception right back to the caller.
    Throw
  Finally
    ' Run this code no matter what happens.
    s = Nothing
  End Try
End Function

The test procedure passes in the file you specify on the sample form, and traps the FileTooLargeException. In that specific Catch block, the code retrieves the FileSize property of the exception, and the code compiles and runs fine (even though a normal Exception object doesn't supply a FileSize property) because this specific exception, the FileTooLargeException, does indeed supply this property:

' User-Defined Exception option on the sample form.
Private Sub UserDefinedException()
  Dim lngSize As Long

  ' Test a user-defined exception.

  Try
    lngSize = GetSize(txtFileName.Text)
  Catch e As FileTooLargeException    MessageBox.Show( _     String.Format( _     "Please select a smaller file! " & _     "The file you selected was {0} bytes.", _     e.FileSize))
  Catch e As Exception
    MessageBox.Show(e.Message)
  End Try
End Sub

**Tip   **You'll find it useful to be able to create your own exception classes, inheriting from the base ApplicationException class whenever you need to add your own information to the standard error information. You might want to create an exception class that provides full stack frame information (that is, some data structure containing the call stack), rather than the simple string the .NET Framework gives you in its StackFrame property. You can do this using the StackTrace class and its members. See the .NET Framework documentation for more information on the StackTrace and StackFrame classes.

Summary

  • Structured exception handling is more powerful than error handling provided by Visual Basic 6.0.
  • Use a Try block to add exception handling to a block of code.
  • Add Catch blocks, as necessary, to trap individual exceptions.
  • The .NET runtime handles Catch blocks in order, looking for an "is a" match against the current exception. It uses the first block it finds that matches.
  • You can nest Try blocks, making it easy to effectively push and pop exception-handling states.
  • Add a Finally block to your Try block to run code unconditionally, regardless of whether an error occurs or not.
  • You can create your own exception classes that inherit from the base Exception class (or any class that inherits from that class) in order to add your own functionality.

About the Author

Ken Getz is a senior consultant with MCW Technologies and splits his time between programming, writing, and training. He specializes in tools and applications written in Microsoft Access, Visual Basic, and the rest of the Office and BackOffice suites. Ken is co-author of several books including Access 97 Developer's Handbook with Paul Litwin and Mike Gilbert, Access 2000 Developer's Handbooks with Paul Litwin and Mike Gilbert, Access 2002 Developer's Handbooks with Paul Litwin and Mike Gunderloy, Visual Basic Language Developer's Handbook with Mike Gilbert, and VBA Developer's Handbook with Mike Gilbert (Sybex). With Paul Sheriff, Ken co-authored a book entitled ASP.NET Jumpstart. Ken co-wrote training materials and teaches for AppDev, is a frequent speaker at technical conferences, and has spoken at the Microsoft Tech*Ed conferences since 1994. Ken is a Technical Editor for Access/VB/SQL Advisor magazine and Contributing Editor for Informant Communication Group's Microsoft Office Solutions magazine.

About Informant Communications Group

Informant Communications Group, Inc. (www.informant.com) is a diversified media company focused on the information technology sector. Specializing in software development publications, conferences, catalog publishing and Web sites, ICG was founded in 1990. With offices in the United States and the United Kingdom, ICG has served as a respected media and marketing content integrator, satisfying the burgeoning appetite of IT professionals for quality technical information.

Copyright © 2002 Informant Communications Group and Microsoft Corporation

Technical editing: PDSA, Inc. or KNG Consulting