VBScript Err Objects

This guide discusses the VBScript Err object.

Overview

The VBScript Err object provides access to run-time error information.

The Err object encapsulates errors for a VBScript script. By default, if an error occurs, VBScript terminates script execution and RhinoScript reports the error back to the user. Sometimes this default error processing is not desirable. In this case, the Err object and the On Error statement can be used to let scripts perform their own error handling.

Details

The Err object is a predefined global object. It does not need to be declared before it can be used. The object is used to encapsulate all the information relating to an error condition. This information is presented as a series of properties:

  • The .Number property is the error number (or code) for the error. This is the default property of the Err object.
  • The .Source property contains a string that specifies the source of the error. This is typically the ProgID (Programmatic Identifier) of the object that generated the error.
  • The .Description property contains a string describing the error.
  • The .HelpFile and .HelpContext properties store information to reference a help topic in a help file. This allows the error to refer to information on possible causes of the error.

Using On Error

To generate a user-defined run-time error, first clear the Err object using the .Clear method. Then raise the error using the .Raise method. This method takes up to five arguments that correspond, in order, to the properties previously listed. For example:

Err.Clear
Err.Raise 1000, "This is a script-defined error", "Test Script"

This example displays the standard RhinoScript error dialog box showing the error information.

To intercept run-time errors and process them in scripts, use the On Error statement. The syntax of this statement is:

On Error Resume Next

After this statement executes, the next run-time errors do not cause script execution to end. Instead, the Err object properties are set to reflect the error information and processing continues with the next statement. For example:

Err.Clear
On Error Resume Next
Err.Raise 100, "Script Error"
If Err.Number Then Rhino.Print "Error=" & CInt(Err.Number)

In this example, the Err.Raise method is used to raise a run-time error. Normally, this would stop script execution. However, the earlier On Error statement allows script execution to continue. So the If statement executes and displays the error number.

In the preceding example, the error was generated by the Err.Raise method. Yet, the same processing applies to any run-time error, regardless of how it is generated. For example:

On Error Resume Next
Err.Clear
x = CInt("foo")
If Err.Number <> 0 Then
  Rhino.Print Err.Number
  Rhino.Print Err.Description
  Rhino.Print Err.Source
End If

Here, an attempt is made to convert the string "foo" into an integer. Because this is an invalid conversion, a run-time type mismatch error is generated. The information on this error is placed in the Err object. This is then processed by the If statement.

After an On Error statement executes, it remains in effect for the rest of the procedure in which it executes. If the On Error statement executes in global scope, it remains in effect until the script terminates. Nested procedures can each have their own On Error statement. For example, subroutine A can execute an On Error statement and then execute subroutine B, which in turn, executes an On Error statement.

If an error occurs while an On Error statement is active, execution continues with the following statement in the same scope as the most recently executed On Error statement. For example:

On Error Resume Next
Rhino.Print "Begin"
Sub1
Rhino.Print "End"
Sub Sub1
  Rhino.Print "Enter Sub1"
  Err.Raise 100
  Rhino.Print "Leave Sub1"
End Sub

In this example, an On Error statement executes at global scope, and then the Sub1 procedure executes. Within this procedure, an Err.Raise method is used to generate an error. Because the most recently executed error is at global scope, the next statement to execute is the Rhino.Print statement at global scope, and not the Rhino.Print statement following the Err.Raise statement. In fact, the error causes VBScript to abandon further execution of the statements in Sub1 and continue execution at global scope. Thus, the output of this script is:

Begin
Enter Sub1
End

Notice that the final Rhino.Print statement in Sub1 never executes. When an error occurs, VBScript immediately abandons execution of any running procedures necessary to resume with the correct statement after an error. For example:

On Error Resume Next
Rhino.Print "Begin"
Sub1
Rhino.Print "End"

Sub Sub1
  Rhino.Print "Enter Sub1"
  Sub2
  Rhino.Print "Leave Sub1"
End Sub

Sub Sub2
  Rhino.Print "Enter Sub2"
  Err.Raise 100
  Rhino.Print "Leave Sub2"
End Sub

Here, the Err.Raise method invocation is nested even more deeply. In this case, when the error occurs, VBScript abandons further execution of both Sub1 and Sub2 to continue execution at the global level.

Because VBScript abandons execution of procedures only until it finds the most recently executed On Error statement, it is possible to capture an error within a procedure simply by placing an On Error statement in that procedure. For example:

On Error Resume Next
Rhino.Print "Begin"
Sub1
Rhino.Print "End"

Sub Sub1
  Rhino.Print "Enter Sub1"
  On Error Resume Next
  Sub2
  Rhino.Print "Leave Sub1"
End Sub

Sub Sub2
  Rhino.Print "Enter Sub2"
  Err.Raise 100
  Rhino.Print "Leave Sub2"
End Sub

This example modifies the previous example by adding an On Error statement to the Sub1 procedure. So, when the Err.Raise method in Sub2 executes, execution continues with the next statement in Sub1. Notice that the Leave Sub2 line never executes. The output from this example is:

Begin
Enter Sub1
Enter Sub2
Leave Sub1
End

Structured Exception Handling

The On Error statement is a simple form of a technique known as structured exception handling. The basic idea behind this technique is to centralize all the error handling code in a single location outside of the main flow of the program. This is the reason for the complex behavior of the On Error statement.

The assumption is that a large script might contain many procedures that interact in complex ways. It is possible that an error will occur when procedures are nested very deeply. Without the On Error statement, each procedure must return some form of error code to the procedure from which it was called. In turn, this procedure must do the same thing, and so on for all the nested procedures. This can greatly add to the complexity of the script.

With the On Error statement, this complexity can be avoided. When an error occurs, VBScript automatically takes care of unwinding out of the complex nest of procedures back to the statement that followed the original procedure invocation.