When I write complex applications broken into function calls, I *always*
combine the (little documented) lsi_info(2) function with an extra "Last Error
Message" parameter to every function call. Then an errorhandler in *every*
function can report the exact location of an error properly.
Sure, this is verbose, but it does guarantee the end-users will be able to help
you find the errors later.
If you also declare all subroutines as Functions, which returns True if it has
no errors (instead of using Subs), you can test for success and decide when to
abandon the agent's run.
Example:
Create a test agent, Run-from-actions-menu, Shared, Run-once, containing the
following code:
Option Public
Option Declare
Sub Initialize
' This agent (when called from a browser) demonstrates error trapping
for web applications
'
' Written: Martin Audley, Oxford, England
'
Dim strLastErrMessage$
On Error Goto ErrorHandler
If bPrintAMessage%("Hello World 1",False,strLastErrMessage$) Then
If bPrintAMessage%("Hello World 2",True,strLastErrMessage$) Then
Call bPrintAMessage%("Hello World 3",False,strLastErrMessage$)
End If
End If
If strLastErrMessage$<>"" Then Print strLastErrMessage$
ExitSub:
Exit Sub
ErrorHandler:
Let strLastErrMessage$=strLastErrMessage$ & "Routine '" & Lsi_info(2) &
"' at line #" & Erl & " generated error message: " & Error$ & "<BR>"
Resume ExitSub
End Sub
Function
bPrintAMessage%(strMessage$,bDoRaiseADeliberateError%,strLastErrMessage$)
' Function returns True if it successfully outputs a line to the web
browser.
On Error Goto ErrorHandler
Print strMessage$ & "<BR>"
If bDoRaiseADeliberateError% Then
Let bPrintAMessage% = bFunctionContainingAnError%(strLastErrMessage$)
Else
Let bPrintAMessage% = True
End If
ExitFunction:
Exit Function
ErrorHandler:
Let strLastErrMessage$=strLastErrMessage$ & "Routine '" & Lsi_info(2) &
"' at line #" & Erl & " generated error message: " & Error$ & "<BR>"
Resume ExitFunction
End Function
Function bFunctionContainingAnError%(strLastErrMessage$)
' Function to deliberately raise a divide-by-zero error to demonstrate error
handling,
On Error Goto ErrorHandler
Dim iDenominator%
Print 1 / iDenominator%
Let bFunctionContainingAnError%=True ' (NB: Never reached - because
of deliberate error)
ExitFunction:
Exit Function
ErrorHandler:
Let strLastErrMessage$=strLastErrMessage$ & "Routine '" & Lsi_info(2) &
"' at line #" & Erl & " generated error message: " & Error$ & ". This routine
was called from parent function " & Lsi_info(12) & ".<BR>"
Resume ExitFunction
End Function
When I write complex applications broken into function calls, I *always* combine the (little documented) lsi_info(2) function with an extra "Last Error Message" parameter to every function call. Then an errorhandler in *every* function can report the exact location of an error properly.
Sure, this is verbose, but it does guarantee the end-users will be able to help you find the errors later.
If you also declare all subroutines as Functions, which returns True if it has no errors (instead of using Subs), you can test for success and decide when to abandon the agent's run.
Example: Create a test agent, Run-from-actions-menu, Shared, Run-once, containing the following code:
Option Public Option Declare
Sub Initialize ' This agent (when called from a browser) demonstrates error trapping for web applications ' ' Written: Martin Audley, Oxford, England ' Dim strLastErrMessage$ On Error Goto ErrorHandler If bPrintAMessage%("Hello World 1",False,strLastErrMessage$) Then If bPrintAMessage%("Hello World 2",True,strLastErrMessage$) Then Call bPrintAMessage%("Hello World 3",False,strLastErrMessage$) End If End If If strLastErrMessage$<>"" Then Print strLastErrMessage$ ExitSub: Exit Sub ErrorHandler: Let strLastErrMessage$=strLastErrMessage$ & "Routine '" & Lsi_info(2) & "' at line #" & Erl & " generated error message: " & Error$ & "<BR>" Resume ExitSub End Sub
Function bPrintAMessage%(strMessage$,bDoRaiseADeliberateError%,strLastErrMessage$) ' Function returns True if it successfully outputs a line to the web browser.
On Error Goto ErrorHandler Print strMessage$ & "<BR>" If bDoRaiseADeliberateError% Then Let bPrintAMessage% = bFunctionContainingAnError%(strLastErrMessage$) Else Let bPrintAMessage% = True End If ExitFunction: Exit Function ErrorHandler: Let strLastErrMessage$=strLastErrMessage$ & "Routine '" & Lsi_info(2) & "' at line #" & Erl & " generated error message: " & Error$ & "<BR>" Resume ExitFunction End Function
Function bFunctionContainingAnError%(strLastErrMessage$) ' Function to deliberately raise a divide-by-zero error to demonstrate error handling, On Error Goto ErrorHandler Dim iDenominator% Print 1 / iDenominator% Let bFunctionContainingAnError%=True ' (NB: Never reached - because of deliberate error)
ExitFunction: Exit Function ErrorHandler: Let strLastErrMessage$=strLastErrMessage$ & "Routine '" & Lsi_info(2) & "' at line #" & Erl & " generated error message: " & Error$ & ". This routine was called from parent function " & Lsi_info(12) & ".<BR>" Resume ExitFunction End Function