Section 11.2. Runtime Error Handling


11.2. Runtime Error Handling

Visual Basic supports both unstructured error handling and structured exception handling. This discussion starts with a look at unstructured error handling , the same error-handling support provided in VB 6. You are not required to include any error handling in a VB procedure. If you do include such handling in a procedure, you must include either the structured or unstructured variety; a single procedure cannot include both types of error-handling methods.

11.2.1. Unstructured Error Handling

Error-handling techniques that revolve around the various On Error... statements are referred to as unstructured error-handling techniques. These techniques generally involve the Err object and the Visual Basic call stack.

11.2.1.1. The Err object

Visual Basic's built-in error object, called Err, has several useful properties and methods, as shown in Tables 11-1 and 11-2, respectively.

Table 11-1. Properties of the Err object

Property

Description

Description

A short string describing the error.

HelpContext

The numeric context ID for a help topic associated with the error.

HelpFile

The fully qualified filename of the associated help file, if available.

LastDLLError

The return code from a call made to a function in an external DLL. This property may change value at any time, so it is wise to store the current value in a variable immediately upon return from the DLL call. VB does not raise errors based on the return value of a DLL function, since it cannot know which return values indicate errors.

Number

The error number of the error.

Source

A string that indicates the object that generated the error. When the error is generated within your application, the Source property is the project programmatic ID. For class-initiated errors, it is in the format project.class. When the error is generated by an external COM component, the Source property returns the programmatic ID of that component, generally in the form application.object.


Table 11-2. Methods of the Err object

Method

Description

Clear

Clears the values of all properties of the Err object. Its syntax is:

     Err.Clear(  ) 

The Clear method is called implicitly when any of the following statements are executed: a Resume statement; an Exit Sub, Exit Function, or Exit Property statement; a try...Catch...Finally statement; or an On Error statement.

Raise

Causes Visual Basic to generate a runtime error and sets the properties of the Err object to the values given by the parameters of the Raise method. Its syntax is:

     Err.Raise(Number[, Source[, Description[, _         HelpFile[, HelpContext]]]]) 

where all but the first named argument is optional. Each parameter corresponds to the property of the same name.


11.2.1.2. Dealing with runtime errors

Visual Basic detects a runtime error as soon as it occurs, sets the properties of the Err object, and directs the flow of execution to a location that the programmer has specified by the most recent On Error statement. This location can be one of the following:

  • The line of code immediately following the line that caused the error

  • Another labeled location within the offending procedure

  • Any enabled error handler within the current procedure's call stack

  • New in 2005. In Windows Forms applications, the error handler associated with the My.Application.UnhandledException event

If none of these methods exist or are enabled (and no structured exception handlers are in use), VB issues an error message and terminates the application. The remainder of this section describes each option in more detail.

Inline error handling. Code execution will be "redirected" to the line following the offending line of code if the most recent On Error statement is:

     On Error Resume Next 

This is referred to as inline error handling . The following example demonstrates this type of error handling in the process of renaming a file. The code specifically examines any error number (Err.Number) generated by the Rename function.

     Dim oldName As String     Dim newName As String     On Error Resume Next     ' ----- Prompt the user for the old and new names.     oldName = InputBox("Enter the file name to rename.")     newName = InputBox("Enter the new file name.")     ' ----- Rename the file.     Err.Clear(  )     Rename("c:\" & oldName, "c:\" & newName)     ' ----- Deal with any error.     If (Err.Number = 53) Then     ' ----- File not found error.     MsgBox("File '" & oldName & "' not found.")     Exit Sub     ElseIf (Err.Number <> 0) Then     ' ----- All other errors.     MsgBox("Error " & Err.Number & ": " & Err.Description)     Exit Sub     End If 

Centralized error handling. Centralized error handling keeps error detection and error handling in the same procedure, but it places all error-handling code in a common location within that procedure. This is especially useful when code detection for a common set of errors occurs multiple times throughout a large procedure. Execution is redirected to the central error-handling code block using the statement:

     On Error GoTo label 

This is outlined in the following code template:

     Public Sub Example(  )     On Error GoTo ErrorHandler     ' ----- If a run-time error occurs here, Visual Basic     '       directs execution to the ErrorHandler label.     Exit Sub     ErrorHandler:     ' ----- Code can be placed here to handle errors directly.     '       Err.Number, Err.Description, and Err.Source can be     '       examined here.     End Sub 

Once the On Error GoTo ErrorHandler statement is executed, the error handler beginning at the label ErrorHandler is active. There are several possibilities for dealing with the error. The most common possibility is simply to handle the error in the active error handler, perhaps by displaying an error message asking the user to take corrective action.

Another common approach is to pass information about an error to the calling procedure through parameters or through the return value of the offending function. For instance, if a function is designed to rename a file, the function might return an integer error code indicating the success or failure of the operation. This method is quite common among the Win32 API functions. In particular, the error code might be 0 for success, -1 if the file does not exist, -2 if the new filename is invalid, and so on.

A third possibility is to pass the error to the calling procedure by invoking the Err.Raise method within the active error handler:

     Err.Raise(Err.Number, Err.Source, Err.Description, _         Err.HelpFile, Err.HelpContext) 

This triggers the next procedure up in the call stack to process the error using its own active error handler. This process is called regenerating or reraising the error. If that procedure does not have an active error handler, the raised error continues up the call stack until it finds a procedure with an active error handler.

No enabled error handler. When you first enter any procedure, error handling is disabled in that procedure until the code encounters some sort of On Error or structured exception-handling statement. Using On Error GoTo label enables centralized error handling, but what if you want to turn off the central error- handling block code? The following statement takes just such an action, restoring the error-handling state to what it was when you first entered the procedure.

     On Error GoTo 0 

Without an enabled error handler, all errors cause execution to move up the call stack to the next procedure, continuing up until an enabled exception handler is found. A lack of exception handlers causes Visual Basic to display an error message and terminate the application.

A third variation of the On Error statement disables an error handler from inside of an error handler:

     On Error GoTo -1 

This statement can be used within a block of error-handling code. It causes the procedure to forget that it is in an error handler; Resume statements will have no impact after using this statement. To reinstate error handling, you must use another On Error statement.

New in 2005. Visual Basic 2005 adds support for a global, central error-handling routine. This feature is only available in Windows Forms applications, and it is accessed through the My.Application.UnhandledException event. The actual procedure for this event is found in the application's ApplicationEvents.vb file, which is hidden from the Solution Explorer view by default. (Click the Show All Files button in the Solution Explorer to display this and other hidden files.) The event procedure has the following form.

     Namespace My         Class MyApplication             Private Sub MyApplication_UnhandledException( _                 ByVal sender As Object, _                 ByVal e As UnhandledExceptionEventArgs) _                 Handles Me.UnhandledException                 ' ----- Special error handling code goes here.             End Sub         End Class     End Namespace 

This special event handler is ignored when running your application within the Visual Studio IDE.

11.2.2. Structured Exception Handling

Structured exception handling uses the TRy...Catch...Finally construct to handle local errors. This is a much more object-oriented approach, involving objects of the System.Exception class and its derived classes.

The syntax of the try...Catch...Finally construct is:

     Try         tryStatements     [Catch [exception [As type]] [When expression]         catchStatements     [Exit Try]]     [Catch [exception [As type]] [When expression]         catchStatements]     ...     [Catch [exception [As type]] [When expression]         catchStatements]     [Finally         finallyStatements]     End Try 

The tryStatements (which are required) constitute the try block and are the statements that are monitored for errors by VB. Error handling is active within the try block.

The Catch blocks (you can include zero or more of these) contain code that is executed in response to VB "catching" a particular type of error within the TRy block. Thus, the Catch blocks consist of the error handlers for the TRy block.

The exception [As type] and [When expression] clauses are referred to as filters. An exception is either a variable of type System.Exception or one of its derived classes. It is by using one of these derived classes that you can narrow the scope of a Catch clause to a specific error. The clause:

     Catch ex As Exception 

will catch any exception for handling within that Catch block. The clause:

     Catch ex As DivideByZeroException 

catches divide-by-zero division errors, but no others. The DivideByZeroException class is one of the classes derived from System.Exception.

The When filter is typically used with user-defined errors. For instance, the code in the following TRy block raises an error if the user does not enter a number.

     Dim userInput As String     Try         userInput = InputBox("Enter a number.")         If Not IsNumeric(userInput) Then Err.Raise(1)     Catch When Err.Number = 1         MsgBox("Supplied data was non-numeric.")     End Try 

The following code will not catch an error, since no true error is generated:

     Dim testNumber As Integer     Try         testNumber = 5     Catch When testNumber = 5         ' ----- Execution will never come here.         MsgBox(testNumber & " is not right.")     End Try 

The Finally clause in a try statement includes any code that must be executed, whether an error occurs or not. This final code can be used for cleanup in the event of an error.

The Exit Try statement can appear anywhere within a try...Catch...Finally block to jump out of the statement immediately. Any remaining Finally clause statements are skipped.

As with unstructured error handling, VB may pass an error up the call stack when using structured exception handling. This happens in the following situations:

  • An error occurs within a try block that is not handled by one of the Catch blocks.

  • An error occurs outside any try block.

11.2.2.1. Exception classes

The following list includes many of the common exception types derived from the System.Exception class. Classes are indented under the class from which they are derived.

     Exception         ApplicationException         SystemException             AccessException                 FieldAccessException                 MethodAccessException                 MissingMemberException                     MissingFieldException                     MissingMethodException             AppDomainUnloadedException             AppDomainUnloadInProgressException             ArgumentException                 ArgumentNullException                 ArgumentOutOfRangeException                 DuplicateWaitObjectException             ArithmeticException                 DivideByZeroException                 NotFiniteNumberException                 OverflowException             ArrayTypeMismatchException             BadImageFormatException             CannotUnloadAppDomainException             ContextMarshalException             CoreException                 ExecutionEngineException                 IndexOutOfRangeException                 StackOverflowException             ExecutionEngineException             FormatException             InvalidCastException             InvalidOperationException             MulticastNotSupportedException             NotImplementedException             NotSupportedException                 PlatformNotSupportedException             NullReferenceException             OutOfMemoryException             RankException             ServicedComponentException             TypeInitializationException             TypeLoadException                 EntryPointNotFoundException             TypeUnloadedException             UnauthorizedAccessException             WeakReferenceException         URIFormatException 

In general, the derived classes provide no additional class members; it is the class instance itself that provides the information needed to distinguish between different types of errors. (It is possible to access the exception class for an error even when you are using the On Error unstructured error-handling methods. The Err object includes a GetException method that returns an instance of the exception class related to the error.)

Some of the derived classes do include additional information that can be useful to your error-processing actions. For instance, the ArgumentException class includes a ParamName property that returns the name of the parameter that causes the exception. The following example demonstrates its use.

     Sub CopyAnImportantFile(  )         Dim sourceFile As String = "c:\temp.txt"         Dim destFile As String = "I am not a file path!"         Try             FileCopy(sourceFile, destFile)         Catch ex As ArgumentException             MsgBox(ex.Message & " Parameter: " & e.ParamName)         End Try     End Sub 

The System.Exception class includes several important members, as listed in Table 11-3.

Table 11-3. Members of the System.Exception class

Member

Description

Data

Property. New in 2005. A dictionary collection used to add additional information to custom exceptions.

Message

Property. A string containing the error message.

Source

Property. A string that describes the application or object that threw the exception. Generally the application's programmatic ID, the COM programmatic ID, or a project.class name for in-class errors.

StackTrace

Property. A string that contains the stack trace immediately before the exception was thrown.

TargetSite

Property. The name of the method that threw the exception.

ToString

Method. Obtains the name of the exception as a string and possible additional information about the current error.


The following example displays the type of content you can except from these class properties. It generates an ArgumentNullException exception manually, which is handled two procedures further up the call stack.

     Public Sub Level1Routine(  )         Dim info As String         Try             Level2Routine(  )         Catch ex As Exception             info = "Message: " & ex.Message & vbCrLf & _                 "Source: " & ex.Source & vbCrLf & _                 "Stack: " & ex.StackTrace & vbCrLf & _                 "Target: " & ex.TargetSite.Name & vbCrLf & _                 "ToString: " & ex.ToString             Debug.WriteLine(info)         End Try     End Sub     Sub Level2Routine(  )         Level3Routine(  )     End Sub     Public Sub Level3Routine(  )         Throw New ArgumentNullException(  )     End Sub 

In Level3Routine, an ArgumentNullException is thrown using the Throw statement, passing a new instance of the exception up the call stack. The output from the call to Level1Routine is as follows (slightly formatted for readability):

     Message: Value cannot be null.     Source: WindowsApplication1     Stack:  at WindowsApplication1.Form1.Level3Routine(  )             in C:\temp\Form1.vb:line 26         at WindowsApplication1.Form1.Level2Routine(  )             in C:\temp\Form1.vb:line 22         at WindowsApplication1.Form1.Level1Routine(  )             in C:\temp\Form1.vb:line 10     Target: Level3Routine     ToString: System.ArgumentNullException: Value cannot be null.         at WindowsApplication1.Form1.Level3Routine(  )             in C:\temp\Form1.vb:line 26         at WindowsApplication1.Form1.Level2Routine(  )             in C:\temp\Form1.vb:line 22         at WindowsApplication1.Form1.Level1Routine(  )             in C:\temp\Form1.vb:line 10 




Visual Basic 2005(c) In a Nutshell
Visual Basic 2005 in a Nutshell (In a Nutshell (OReilly))
ISBN: 059610152X
EAN: 2147483647
Year: 2004
Pages: 712

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net