TRY...CATCH...FINALLY Command
Provides a structure to handle errors and exceptions that can occur while running a block of code.
For more information about structured error handling using the TRY...CATCH...FINALLY command, see Structured Error Handling.
TRY
[ tryCommands ]
[ CATCH [ TO VarName ] [ WHEN lExpression ]
[ catchCommands ] ]
[ THROW [ eUserExpression ] ]
[ EXIT ]
[ FINALLY
[ finallyCommands ] ]
ENDTRY
Parameters
TRY
Indicates the beginning of the TRY...CATCH...FINALLY structure.[ tryCommands ]
Specifies statements where an error might occur.[CATCH]
Indicates the beginning of a CATCH block, which handles the appropriate error. You can specify a CATCH statement without arguments, which evaluates to CATCH WHEN .T. (True).Tip
If you want to have a TRY...CATCH...FINALLY structure that catches all errors, make sure you have a CATCH statement that always evaluates to True (.T.).
You can specify any number of CATCH statements, including none.
[TO VarName]
Specifies a memory variable and not an object reference that stores a reference to the Exception object created. VarName can be only a simple memory variable, not an object property reference.You can explicitly set VarName to any value in the TRY...CATCH...FINALLY structure. The value does not change as long as another CATCH statement does not run, which resets VarName to NULL.
VarName can have local, public, or private scope, which depends on how the variable is declared. If VarName has not been previously declared, it has private scope. The Exception object created has the same scope as VarName. When VarName goes out of scope, is released, or is reset, the Exception object is also released.
When a CATCH TO VarName clause executes, Visual FoxPro always sets the VarName to a new Exception object regardless of its previous setting, though VarName retains its scope. Therefore, the contents of VarName are always overwritten regardless of what it previously referenced.
[WHEN lExpression]
Specifies an optional logical expression to evaluate when the program encounters the CATCH statement. The expression must evaluate to True (.T.) for the corresponding catchCommands to run.The argument for lExpression can contain a reference to the VarName Exception object so that you can query the resulting error and handle it accordingly.
If a WHEN clause evaluates to False (.F.), Visual FoxPro releases the Exception object and resets the VarName to NULL. You can test whether VarName is set to a type or to NULL by using the VARTYPE( ) function.
[ catchCommands ] ]
Specifies statements to run when the program encounters the corresponding CATCH statement.[THROW [ eUserExpression ] ]
Creates a new Exception object to be caught by a CATCH statement. You can call THROW from any code block in 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.
Note
Run-time applications should enclose a THROW command with an outer TRY...CATCH...FINALLY structure. Visual FoxPro disregards any THROW statements appearing in a CATCH WHEN lExpression clause.
The eUserExpression parameter specifies an expression of any type and sets the exception's UserValue property. You can pass an object of any type because the exception's UserValue property stores only the object reference.
When you include eUserExpression with the THROW clause, Visual FoxPro sets the exception's ErrorNo property value to 2071, which corresponds to the error, "User Thrown Error (Error 2071)".
Note
You should pass a value for eUserExpression, which sets the exception's UserValue property, so you can chain multiple Exception objects. For more information about chaining Exception objects, see the Example section.
If you omit eUserExpression, Visual FoxPro escalates the original Exception object, if it exists. If the Exception object does not exist, Visual FoxPro throws a new Exception object with an ErrorNo property value of 2071. If you omit eUserExpression, and the THROW clause escalates the Exception object to an outer TRY...CATCH block, the outer TRY...CATCH block catches the same Exception object. Values returned by the ERROR( ), MESSAGE( ), and AERROR( ) functions might not be reliable when used in a structured exception handler, so, you should use the Exception object instead.
If an outer TRY...CATCH statement is in effect when THROW is called from a CATCH or FINALLY block, Visual FoxPro assigns VarName in the CATCH TO clause to the object reference for the Exception object generated by the thrown exception. If no outer TRY...CATCH statement is in effect, Visual FoxPro escalates the exception to an ON ERROR or Error event, if one exists; otherwise, Visual FoxPro calls its system error handler.
If you want to rethrow the original exception that was caught by the CATCH TO VarName clause, you can call THROW VarName to rethrow the exception.
Note
Rethrowing the original exception produces another new Exception object, at the outer CATCH statement, that has a UserValue property containing an object reference to the original exception.
If THROW encounters an error when evaluating an expression, Visual FoxPro escalates the error in the usual way.
[EXIT]
Include in a TRY, CATCH, or FINALLY block to immediately stop processing code in a code block.If EXIT appears in the TRY or CATCH block, the program resumes execution at the FINALLY statement, if one exists. If EXIT appears in the FINALLY block or if FINALLY does not exist, the program resumes execution immediately following the ENDTRY statement.
For more information, see EXIT Command.
[ FINALLY
Indicates the beginning of the FINALLY block, which you use to clean up any resources allocated by the TRY block and always runs except when the CANCEL and QUIT commands are used.[ finallyCommands ]
Specifies statements to run in the FINALLY block after either finding no errors in the TRY block or running statements in a CATCH block.ENDTRY
Indicates the end of the TRY...CATCH...FINALLY structure. Each TRY...CATCH...FINALLY structure must end with an ENDTRY keyword. As with other Visual FoxPro control statements, you can add comments prefaced by double ampersand (&&) characters after this ENDTRY.Note
If you do not include the ENDTRY statement at the end of the TRY...CATCH...FINALLY structure, Visual FoxPro generates an error when you compile your code. Although you can still execute code with compile errors, you should not do so in this scenario because it causes Visual FoxPro to stop responding.
Remarks
You cannot explicitly transfer program execution to a CATCH or FINALLY code block.
Visual FoxPro determines scope for variables on a procedural, not block, basis. That is, variables declared in a TRY block are visible from a FINALLY block within the same TRY...CATCH...FINALLY structure. However, in a nested structure, variables that are declared in a TRY, CATCH, or FINALLY block have local scope.
You should not initialize variables or set up critical code inside the TRY block because the code is not guaranteed to run. If an error occurs at a particular line of code in the TRY block, all subsequent lines in the TRY block do not run.
Any errors that occur in an object's Error event must be handled by the object and are not escalated to an ON ERROR routine or TRY...CATCH...FINALLY handler. However, you can use a TRY...CATCH...FINALLY structure in the Error event to catch errors from an Error event. For more information, see Error Event (Visual FoxPro).
Using the COMRETURNERROR( ) function in a CATCH block ends all further processing and returns control of the program directly to the Component Object Model (COM) client. Therefore, if you have a FINALLY block, it does not run. For more information, see COMRETURNERROR( ) Function.
Avoid using the SET TEXTMERGE TO MEMVAR command within a TRY...CATCH...FINALLY structure because the memory variable will be lost if an error occurs in the statement.
To determine a course of action and the error handler in effect, use the SYS(2410) - Error Handler function in your TRY...CATCH...FINALLY code, for example, with a DO CASE structure, depending on the type of handler that handles the exception. For more information, see SYS(2410) - Error Handler.
You can use TRY...CATCH...FINALLY to handle errors that occur in menu and timer events and with commands such as ON KEY LABEL if the structure is properly wrapped. The following example illustrates how the READ EVENTS command retains control of the program within the TRY...CATCH...FINALLY structure so that you trap menu events. Error trapping is controlled by the position of TRY...CATCH...FINALLY on the call stack.
TRY
DO myMenu.mpr
DO FORM myForm
myForm.AddObject("tm1","mytimer")
READ EVENTS
CATCH TO oException
IF oException.ErrorNo = 1
STRTOFILE("Error occurred at: " + TRANSFORM(DATETIME());
+ CHR(13),"C:\Errors.log",.T.)
ENDIF
FINALLY
CLEAR EVENTS
ENDTRY
For more information, see READ EVENTS Command and ON KEY LABEL Command.
Visual FoxPro supports Set Next Statement debugging functionality only within a single code block. For example, when executing code in a TRY block, you can use Set Next Statement only to another line within the TRY block. You cannot jump to another line of code in a CATCH or FINALLY block. For more information, see Debugger Keyboard Shortcuts and Menus.
Visual FoxPro generates the appropriate system messages under the following conditions:
A mismatch or error occurs with the TRY...CATCH...FINALLY structure.
An unhandled exception occurs.
A command that is not permitted for a specific block appears in a TRY, CATCH, or FINALLY block. For more information, see Structured Error Handling.
A user-thrown error occurs.
Similar to other error handling in Visual FoxPro, exceptions that occur in TRY...CATCH...FINALLY exception handlers set the SET CONSOLE command to ON. For more information, see SET CONSOLE Command.
Example
The following example illustrates how to nest TRY...CATCH statements, use the THROW clause, and handle Exception objects.
LOCAL x AS Integer, y AS Integer, result AS Integer
LOCAL oErr AS Exception, oErr1 AS Exception
TRY
x = 1
TRY
USE nothing
GO TOP
y = nothing.col1
CATCH TO oErr
oErr.UserValue = "Nested CATCH message: Unable to handle"
?[: Nested Catch! (Unhandled: Throw oErr Object Up) ]
?[ Inner Exception Object: ]
?[ Error: ] + STR(oErr.ErrorNo)
?[ LineNo: ] + STR(oErr.LineNo)
?[ Message: ] + oErr.Message
?[ Procedure: ] + oErr.Procedure
?[ Details: ] + oErr.Details
?[ StackLevel: ] + STR(oErr.StackLevel)
?[ LineContents: ] + oErr.LineContents
?[ UserValue: ] + oErr.UserValue
THROW oErr
FINALLY
?[: Nested FINALLY executed ]
IF USED("nothing")
USE IN nothing
ENDIF
ENDTRY
result = x-y
CATCH TO oErr1
?[: Outer CATCH! ]
?[ Outer Exception Object: ]
?[ Error: ] + STR(oErr1.ErrorNo)
?[ LineNo: ] + STR(oErr1.LineNo)
?[ Message: ] + oErr1.Message
?[ Procedure: ] + oErr1.Procedure
?[ Details: ] + oErr1.Details
?[ StackLevel: ] + STR(oErr1.StackLevel)
?[ LineContents: ] + oErr1.LineContents
?[ ->UserValue becomes inner exception THROWn from nested TRY/CATCH ]
?[ Error: ] + STR(oErr1.UserValue.ErrorNo)
?[ Message: ] + oErr1.UserValue.Message
?[ Procedure: ] + oErr1.UserValue.Procedure
?[ Details: ] + oErr1.UserValue.Details
?[ StackLevel: ] + STR(oErr1.UserValue.StackLevel)
?[ LineContents: ] + oErr1.UserValue.LineContents
?[ UserValue: ] + oErr1.UserValue.UserValue
result = 0
FINALLY
?[: FINALLY statement executed ]
ENDTRY
RETURN result
The following example shows how you might want to chain Exception objects:
TRY
TRY
x=y && The y variable does not exist and causes an error.
CATCH TO oException2
THROW CREATEOBJECT("myException")
ENDTRY
CATCH TO oException1
ENDTRY
? 2, oException2.ErrorNo, oException2.UserValue
? 1, oException1.ErrorNo, oException1.UserValue.UserValue
DEFINE CLASS myException AS Exception
UserValue = "My custom error handler"
PROCEDURE Init
STRTOFILE("An error occurred at: " + TRANSFORM(DATETIME());
+ CHR(13),"c:\errs.log",.T.)
ENDPROC
ENDDEFINE
See Also
Reference
Exception Class (Visual FoxPro)
SYS(2018) - Error Message Parameter