Error handling in Visual Basic .NET or in Visual Basic 2005 (311326)



The information in this article applies to:

  • Microsoft Visual Basic 2005
  • Microsoft Visual Basic .NET (2003)
  • Microsoft Visual Basic .NET (2002)

This article was previously published under Q311326

SUMMARY

This article discusses the options for handling exceptions in Microsoft Visual Basic .NET or Microsoft Visual Basic 2005.

MORE INFORMATION

Visual Basic .NET or Visual Basic 2005 supports two different ways to keep an unexpected error from terminating an application: unstructured error handling and structured error handling. These events are run-time errors--also called exceptions-- that are responses to abnormal or exceptional conditions that are caused by the execution of a block of code.

Unstructured error handling is the name that is used in Visual Basic .NET or Visual Basic 2005 to refer to the error handling method that is used in Microsoft Visual Basic 6.0. Structured error handling is introduced for the first time to Visual Basic programmers in .NET and is performed by using the Try...Catch...Finally statement, which has long been a feature of other programming languages. Structured error handling introduces a simpler way to create and maintain programs with robust, comprehensive error handlers.

Although Visual Basic .NET or Visual Basic 2005 supports both methods, the methods cannot be implemented simultaneously in the same procedure. The only exception to this is the Error statement, which can be used in structured error handling. It is recommended that all error handling in Visual Basic .NET or Visual Basic 2005 be performed with structured error handling. Unstructured error handling can degrade the performance of the application and result in code that is difficult to debug and maintain.

In the case of a run-time error, both error handling methods look for a local error handler that is defined in a particular block of code. If no local error handler is present, the exception is propagated up the call stack, until a matching handler is found. The call stack represents all procedures that have been called prior to the current point of execution and have not yet been terminated. If no handler is found in the procedures in the call stack when an error occurs, the application is terminated.

Unstructured Error Handling

Unstructured error handling is implemented with the On Error statement, which is placed at the beginning of a code block to handle all possible exceptions that occur during the execution of the code. All Visual Basic 6.0 error handlers in .NET are objects that can be accessed by using the Microsoft.VisualBasic.Information.Err namespace. The handler is set to Nothing each time the procedure is called. You should place only one On Error statement in each procedure, because additional statements disable all previous handlers that are defined in that procedure.

On Error Statement

The On Error statement is used to enable an error-handling routine, disable an error handling routine, or specify where to branch the code in the event of an error.
   On Error { GoTo [ line | 0 | -1 ] | Resume Next }
				
GoTo line

Used to enable the error-handling routine, starting at the location that is specified by the line argument. The line argument can be either a line label or a line number that is located within the closing procedure. A run-time error activates the error handler and branches the control to the specified line. If the specified line is not located within the same procedure as the On Error statement, a compile error occurs.

To avoid unexpected behavior, place an Exit Sub statement, an Exit Function statement, or an Exit Property statement just before the line label or line number. This prevents the error-handling code from running when no error has occurred.

GoTo 0

Disables the enabled error handler that is defined within the current procedure and resets it to Nothing.

GoTo -1

Disables the enabled exception that is defined within the current procedure and resets it to Nothing.

Resume Next

Moves the control of execution to the statement that follows immediately after the statement that caused the run-time error to occur, and continues the execution from this point forward. This is the preferred form to use to access objects, rather than using the On Error GoTo statement.

Example

In the following example code, the error handler is enabled on the first line of the routine with the On Error GoTo Unstructured statement. The location of the error handling routine is identified with the Unstructured line label. The error routine implements a simple Select Case statement that executes the corresponding block of code, depending on the error that occurred.

The Resume Next statement at the end of the error handling procedure returns control of the execution back to the line that follows the line that caused the error to occur.

The error handler is then disabled with the On Error GoTo 0 statement, followed by the On Error Resume Next statement, which reactivates the error handler. If a run-time error occurs, the statement causes the execution to branch to the line that immediately follows the line that caused the error to occur, the same way that the Resume Next statement does in the error handling routine. In this case, that line is the If statement that evaluates the error number and displays it to the user, as well as clearing the error object.
   Public Sub fnErrors()
   On Error GoTo Unstructured ' Enable error handler

     Dim Result As Integer
     Dim Value1 As Integer = 9
     Dim Value2 As Integer = 0
 
     On Error GoTo 0 ' Disables the error handler
 
     'Moves execution to the line following the line that caused the error.
     On Error Resume Next
 
     Result = Value1 / Value2 ' Division by zero, cause an overflow error.
 
     ' Catch the overflow error caused by dividing by zero.
     If Err.Number = 6 Then
       MessageBox.Show("Error Number: " & Err.Number.ToString)
       Err.Clear() ' Clear Errors
     End If
     Exit Sub

   Unstructured:  ' Location of error handler
     Select Case Err.Number
       Case 6
         ' Display the error number.
         MessageBox.Show("Divided by zero")
       Case Else
         ' Catch all other type of errors.
         MessageBox.Show(Err.Description)
     End Select
     'Resume execution to the line following the line that caused the error.
     Resume Next
   End Sub
				

Structured Error Handling

With structured error handling, Visual Basic now has an effective way to prevent unexpected errors from terminating the execution of the application. Structured error handling also provides the programmers with a simpler way to create robust applications that are easier to maintain.

Structured error handling is implemented in Visual Basic. NET or Visual Basic 2005 with a Try...Catch...Finally block of statements. The Try...Catch...Finally block provides, for the first time to Visual Basic, the capability of nested error handling.

Try...Catch...Finally Statements

The following code demonstrates the structure of a Try...Catch...Finally statement.
   Try 
     'Encapsulates a block of code that may produce a run-time error.
   Catch [Optional Filters]
     'The code runs if any of the statements in the Try block fails and filter is evaluated as true.
   [Additional Catch Blocks]
   Finally
     'Code executed after Try and Catch statement.
   End Try
				
The code that is expected to generate a run-time error should be placed in the Try block for monitoring by the error handler. If this code produces an error during execution, Visual Basic examines all of the Catch statements implemented within the Try...Catch...Finally block to find a condition that matches the error. If Visual Basic finds a matching condition, the control of execution is transferred to the first line of code within the Catch statement. If Visual Basic does not find a matching condition, the error is propagated to the outer Try...Catch...Finally statement. This statement can be located in the same procedure (nested statements) or in a previous procedure that called the one that produced an error. This process is repeated until a matching statement is found. If a matching statement is not found, an error is produced, and the application is terminated.

The Finally statement is executed last, regardless of whether any errors were found. In other words, if no matching Catch statement is found, the Finally statement executes prior to the propagation to the outer statements.

This hierarchy and propagation are demonstrated with the following code:
   Module StructuredError
     Sub Main()
       Try
         fnStructured()
       Catch ex As Exception ' Catches all exceptions.
         Debug.WriteLine("Exception Information: " & vbCrLf & ex.ToString)
         'Displays the representation of current exception.
       Finally
         Debug.WriteLine("Main: Finally executed !")
       End Try
     End Sub

     Public Sub fnStructured()
       'Nested Error Handling
       Try
         Try
           Dim X As Integer = 9
           Dim Y As Integer = 0
           Dim Result As Integer
           Result = X / Y
         Catch e As DataException ' Catches only DataException.
           'Displays the representation of current exception.
           Debug.WriteLine("Exception Information: " & vbCrLf & e.Message) 
         Finally
           Debug.WriteLine("fnStructured: Inner Finally executed !")
         End Try
       Catch e As InvalidCastException ' Catches only defined exception.
         'Displays the representation of current exception.
         Debug.WriteLine("Exception Information: " & vbCrLf & e.ToString)
       Finally
         Debug.WriteLine("fnStructured: Outer Finally executed !")
       End Try
     End Sub
   End Module
				
In the preceding example, an error is generated in a fnStructured() procedure. This is a Stack Overflow error, caused by division with a zero (0). This procedure implements two Try...Catch...Finally blocks of statements, but neither one has matching Catch statements, and the error is not caught. Before the control is propagated in the call stack, the code that is encapsulated in the Finally block is executed. The Try...Catch...Finally block that is implemented in the Sub Main has a general condition that catches all exceptions that are thrown in its Try block.

The following is the output of the preceding procedure:
fnStructured: Inner Finally executed !
fnStructured: Outer Finally executed !
Exception Information:
System.OverflowException: Arithmetic operation resulted in an overflow. at
StructuredError.StructuredError.fnStructured() in C:\Documents and
Settings\heikkiri\My Documents\Visual Studio Projects\Temp\StructuredError\StructuredError.vb:line 21 at 
StructuredError.StructuredError.Main() in C:\Documents and 
Settings\heikkiri\My Documents\Visual Studio
Projects\Temp\StructuredError\StructuredError.vb:line 5
Main: Finally executed !
				

The Err Object

The Err object, which is inherited from Microsoft Visual Basic 6.0, can only be used to catch errors in a procedure that implements unstructured error handling with the On Error statement.

The Err object contains information about a run-time error that occurred during the execution of the application. As the execution enters a procedure that contains error handling, the properties of the Err object are set to zero (0) or zero-length-string (""). If an error occurs during the execution, the properties are then set to provide unique information about the error that occurred, through its properties. An instance of the Err object can be obtained through a Microsoft.VisualBasic.Information.Err function; however, because the Err object is an intrinsic object with global scope, it is not necessary to create an instance of this object at run time.

In case of a run-time error, the properties of the Err object can be used to handle the error (depending on its type), as well as to display information to the user about the error that occurred. The following table shows the different properties that are associated with the Err object.

PropertyDescription
DescriptionReturns or sets a string that contains a description of the error that occurred.
ErlReturns an integer value that indicates the line number of the last statement that was executed.
HelpContextReturns or sets an integer that contains the context ID for the topic, a Help file.
HelpFileReturns or sets a string expression that contains the full path of the Help file that is associated with the error.
LastDLLErrorReturns a system error code that is produced by a call to a dynamic-link library (DLL) file.
NumberReturns or sets a numeric value that specifies the error.
SourceReturns or sets a string that specifies the name of the object or application that originated the error.

The Err object has two methods associated with it: Raise and Clear.

MethodDescription
ClearUsed to clear all of the properties of the Err object.
RaiseUsed to generate a run-time error, identified with the error number that is passed as one its parameters.

Exception Class

   System.Object
      System.Exception
				
As stated earlier in this article, the preferred method of error handling in Visual Basic .NET or Visual Basic 2005 is structured error handling, which is implemented with a Try...Catch...Finally block. All exceptions that are caught in Visual Basic .NET or Visual Basic 2005 are derived from this class, for example, OverFlowException. In case of a run-time error, Visual Basic .NET or Visual Basic 2005 throws an Exception object that can be either system generated or custom generated. The method for catching these Exceptions is described in the "Structured Error Handling" section of this article.

When the exception is thrown, the global Err object is set to the corresponding values, and a new instance of an Exception object is created. This instance contains more information about the error that occurred. For example, the StackTrace property contains a list of methods that were called and led to the occurrence of the error.

The following table shows the public properties that are available for the exceptions that are caught in the structured error handling.

PropertyDescription
HelpLinkReturns or sets the link to the Help file that is associated with this exception.
InnerExceptionReturns an instance of the exception that caused the current exception to occur.
MessageReturns a message that describes the exception.
SourceReturns or sets the name of the application or object that caused the error.
StackTraceReturns a string that presents the frames in the call stack at the time when the exception was thrown.
TargetSiteReturns the method that threw the exception.


The following table shows the public methods that are implemented by the Exception class.

MethodDescription
Equals (inherited from Object)Overloaded method that is used to determine whether two instances of Object are equal.
GetBaseExceptionWhen this method is overridden in a derived class, it returns the exception that is the root cause of one or more subsequent exceptions.
GetHashCodeServes as a hash function for a particular type; suitable for use in hashing algorithms and structures.
GetObjectDataWhen overridden in a derived class, GetObjectData sets the SerializationInfo with information about the exception.
GetType (inherited from Object)Returns the type of the current instance.
ToStringOverridden function that creates and returns a string presentation of the exception.

The Err object was retained in Visual Basic .NET or Visual Basic 2005 for compatibility reasons and to ease the migration from Visual Basic 6.0 to Visual Basic .NET or Visual Basic 2005 applications. It is recommended that all error handling in Visual Basic .NET or Visual Basic 2005 applications be performed by using structured error/exception handling.

REFERENCES

Help Files:
  • Structured Exception Handling
  • Unstructured Exception Handling
  • Err Object
  • Exception Class

Modification Type:MinorLast Reviewed:10/3/2006
Keywords:kbvs2005swept kbvs2005applies kbinfo KB311326 kbAudDeveloper