Structured Error Handling

You can use the TRY...CATCH...FINALLY command as a control structure to handle errors, or exceptions, that might occur in your code at run time. The TRY...CATCH...FINALLY structure contains TRY, CATCH, and FINALLY code blocks so you can specify statements that might generate errors, statements to handle those errors, and statements to perform clean up operations.

The TRY...CATCH...FINALLY structure begins with the TRY statement, which marks the beginning of the TRY block. In the TRY block, you can specify code that might produce errors at run time. If your program completes the TRY block without generating an error, or exception, it skips the CATCH block and searches for the FINALLY block near the end of the structure, if it exists, and runs the corresponding statements. If the FINALLY block does not exist, the program execution continues outside the structure at the first statement following the ENDTRY statement, which marks the end of the TRY...CATCH...FINALLY structure.

Note

Visual FoxPro permits the existence of TRY...CATCH...FINALLY structures that do not have CATCH and FINALLY blocks, which escalate the error to a higher-level error handler.

You can also nest TRY...CATCH...FINALLY structures in a TRY, CATCH, or FINALLY block.

The following sections describe the error-handling tasks you can perform in these code blocks:

  • Generating Exceptions

  • Catching Exceptions

  • Escalating Exceptions

  • Exiting TRY...CATCH...FINALLY Immediately

  • Using Commands in TRY...CATCH...FINALLY

  • Running FINALLY Statements

For more information, see TRY...CATCH...FINALLY Command.

Generating Exceptions

Visual FoxPro generates or "throws" an exception and creates an Exception object, which contains details about the error, when an error occurs in a TRY block in the following locations:

  • A line of code. This includes calls to external procedures that contain errors but does not contain their own error handlers.

  • A method call for an object when the method code contains errors, and the object does not contain Error event code.

    Otherwise, if Error event code exists, the Error event for that object handles the error unless the method contains its own TRY...CATCH...FINALLY error handler.

Note

You cannot run code when the Exception object is created. The Exception object created always exists as an instance of the Exception base class. If you want to use a subclass of the Exception class, you should rethrow the exception in the CATCH or FINALLY block. Only Visual FoxPro program (.prg) files support Exception objects, though you can throw exceptions from forms run in the design environment. You cannot throw Exception objects from COM objects in dynamic-link library (.dll) files or executable (.exe) files. For more information, see Exception Class.

After the error occurs, Visual FoxPro handles or "catches" the exception by moving to the first CATCH statement, and searches for appropriate statements in the CATCH block to handle the exception.

Catching Exceptions

The program looks at the CATCH statements in the order that they appear in the CATCH block to determine statements exist to handle the exception. If the program finds a CATCH statement that handles the exception, the program runs the corresponding code.

The CATCH statement can contain optional TO and WHEN clauses. You can store a reference to the created Exception object by specifying a memory variable using the VarName parameter in the TO clause. If you want to establish a condition for a CATCH block to run, you can specify a logical expression in the WHEN clause that must evaluate to True (.T.) before statements in the CATCH block run. CATCH statements work similarly to CASE statements in that the WHEN clause must evaluate to a logical expression. If the TO and WHEN clauses do not exist, the CATCH statement evaluates as CATCH WHEN .T. (True).

After the program runs statements in a CATCH block, it does not return to the TRY statement, and it does not look for other CATCH statements. Instead, the program proceeds directly to the FINALLY statement, if it exists, to run any remaining statements. Otherwise, the program exits the TRY...CATCH...FINALLY structure and moves to the statement that immediately follows ENDTRY.

Escalating Exceptions

If you want to escalate or "rethrow" the exception to a higher-level error handler, you can include a THROW statement. You can call THROW from any code block of a TRY...CATCH...FINALLY structure. However, you can use THROW anywhere in code where an error handler exists to catch the exception. You cannot call THROW from the Command window.

Warning

Calling the THROW command outside the TRY...CATCH...FINALLY structure and without an appropriate error handler causes your program to quit.

If you use THROW outside the TRY...CATCH section where the thrown exception is handled by an ON ERROR routine or the Visual FoxPro system instead of an Error event, program execution does not return to the location where the THROW statement occurs. The following example shows how the line of code, ?2, does not execute. This behavior differs from a traditional error behavior in which program execution returns to the location where the error occurred:

ON ERROR ? ERROR()
DO myProc1

PROCEDURE myProc1
   ?1
   THROW 11
   ?2
ENDPROC

Remember, the intention for calling THROW is to escalate the exception to a higher-level error handler.

If an outer TRY...CATCH block exists around a THROW statement when it is called from within a CATCH or FINALLY block, Visual FoxPro reassigns the memory variable specified in the TO clause from the object reference of the previous exception object to an object reference for the most recent exception object created by the thrown exception. If no outer TRY...CATCH structure exists, Visual FoxPro throws the exception to an ON ERROR routine or an error event, if they exist. Otherwise, Visual FoxPro displays the appropriate system error message.

Exiting TRY...CATCH...FINALLY Immediately

You can exit a code block immediately by including an EXIT statement in a TRY or CATCH block. The program resumes running code at the FINALLY statement, if one exists, or at the line immediately following the ENDTRY statement.

Using Commands in TRY...CATCH...FINALLY

You can use different Visual FoxPro commands that affect how code normally runs from within a TRY or CATCH block. However, if you use one of these commands that are not permitted for a specific block, Visual FoxPro generates an error at run time. The FINALLY statements always run before handling these commands except when CANCEL or QUIT is used. The following table lists the Visual FoxPro commands you can and cannot use in a TRY, CATCH, or FINALLY block.

Command TRY CATCH FINALLY

CANCEL

Yes

Yes

Yes

CLEAR ALL

Yes

No

No

CLOSE ALL

Yes

Yes

Yes

DOEVENTS

Yes

Yes

Yes

ERROR

Yes

Yes

Yes

EXIT

Yes

Yes

Yes

LOOP

No

No

No

QUIT

Yes

Yes

Yes

RELEASE

Yes

Yes

Yes

RESUME

Yes

Yes

Yes

RETRY

No

No

No

RETURN

No

No

No

RETURN TO MASTER

No

No

No

RETURN TO <ProcedureName>

No

No

No

SET STEP ON

Yes

Yes

Yes

SUSPEND

Yes

Yes

Yes

THROW

Yes

Yes

Yes

Note

You can include commands such as LOOP in a block as long as you place it inside an embedded control statement such as FOR EACH...ENDOR or DO WHILE...ENDDO. You can call the ERROR command from the TRY, CATCH, or FINALLY blocks. TRY...CATCH...FINALLY handles the ERROR command like any other exception or use of the THROW command.

Running FINALLY Statements

If the program locates the FINALLY statement, it runs the code that is in the FINALLY block. The FINALLY block usually cleans up any resources allocated by the TRY block and is always the last code to run before control leaves the TRY...CATCH...FINALLY structure.

The FINALLY block always runs when an exception, unhandled or otherwise, occurs, even if another exception handler such as the ON ERROR routine or an object's Error event is in effect.

Note

You cannot explicitly transfer control of your program directly to a CATCH or FINALLY block. You cannot bypass the FINALLY statement if it exists unless you use the CANCEL command to stop the program from continuing. If you wish to bypass the FINALLY statement, you need to provide code at the beginning of the FINALLY block that checks for a condition and breaks out of the block if that condition is met.

After the FINALLY block runs, the program then proceeds to the statement immediately following the ENDTRY statement. The ENDTRY statement ends the TRY...CATCH...FINALLY structure.

See Also

Reference

Debugging and Error-Handling Language

Concepts

Class and Object Error Handling
Procedural Error Handling
Error Handler Priority
Handling Run-Time Errors

Other Resources

Testing and Debugging Applications