Wiki Home

Error Event Strategy

Namespace: WIN_COM_API
A place to discuss Error Event strategies
Upon error in an object instance, if there is anything at all in an error event, this code will fire and the global event handler will not fire. This is the key concept behind VFP's error handling for objects.
It's often desirable to have different Error Handling depending on whether you are in Development Mode or Production Mode. With a Non Visual Class, you can easily do this with an #IF...#ENDIF bracket around the Error Event. You cannot do this with a Visual Class, because there is no way to bracket a snippet with #IF...#ENDIF.
You can use #IF...#ENDIF inside of a method just as easily as you can in a .PRG -- df Yes, compiler directives can be used in general in methods from VCXs, but with the Error method, any code, even #IF will cause the error method to run--and not the default VFP error behavior that is most convenient is development mode.-- Charlie Schreiner
Charlie, I never find the VFP error handler convenient. grin All of my lowest level classes route errors to an ObjError() UDF. The UDF has has a test to see if it's running in Development Mode or Production Mode. The UDF can be easily swapped out at build time with a #IF directive. -- ?df
Actually, I found a trick to do this, but it's somewhat flaky. You don't put any code in Error. You create a new method called, say error_hidden and put your production error code in it. Now in your included header file, do this:
DEFINE error_hidden ERROR
Now, when debugging, the class has no error method code and VFP error handling (or whatever) kicks in. I recently suggested this to Rick Strahl. He played with it a bit, and found that sometimes it worked and sometimes the compiler got confused. It will be interesting to see if it works in future VFP versions. -- Randy Pearson
One common Error event strategy for objects in Container Classes is to raise the error to This.parent or to ThisForm. Thus the drill is:
  1. Each object handles the errors that it can reasonably expect in its This.error event.
  2. If untrapped, the error is then passed to This.parent.error() or to Thisform.error()
  3. And thereafter the error, if untrapped, bubbles upward through containership, then upward through backlinks to form and application manager objects (say) where it can be finally trapped by the big-daddy error handler of last resort.
This is an allusion to the classic Chain Of Responsibility design pattern, illustrating an implicit containership responsibility chain, followed by an explicit mechanism to delegate to manager objects until a sweet end is reached. -- Steven Black

For a detailed example of this type of error handler (including source code samples), see the Error Handling white paper available from the Technical Papers page of the StoneField Web site. -- Doug Hennig
Doug: Great paper! One question on your RevertAllTables strategy. It was written prior to the advent of the SESSION base class, and finds cursors in private datasessions by iterating the _screen object's forms. How would you discover cursors in need of reverting that were created in Session objects? -- Randy P
You might think you could use code like this:
on error llError = .T.
llError = .F.
for lnI = 1 to 32768
    set datasession to lnI
    if llError
* do something
    endif llError
next lnI
on error
However, the problem is that we're in an error condition, so you definitely don't want to trigger another error (which this code counts on to know when to stop). I think you'd have to do a CLEAR EVENTS and RETURN TO (routine containing READ EVENTS) to get out of the error condition, then after the READ EVENTS statement, check if an error occurred (eg. something like oError.lSomethingReallyBadHappened) and if so, use code like above to handle it. -- Doug Hennig

Error handling gets more interesting when designing classes that will be part of a middle tier (COM object). There is, of course, no UI available to present the error to the user. You need a coordinated way of returning error info to the front end, and you need to ensure that your front end checks for and is prepared to deal with exceptions encountered in middle tier components. (It would be nice if your VFP code could raise COM errors.) VFP6 can raise errors using COMReturn Error(). - Todd Chandler
Cool. Sounds like you could use this conditionally, based on Application.StartMode, so the same class could behave differently in a middle tier setting. -- Randy Pearson
Category Error Handling Category Exam 70-155 Hot Topic
( Topic last updated: 1999.11.09 10:50:00 PM )