ErrHandler Help


Contents | Bottom

ErrHandler is a VFP programming tool that makes it easier to create, debug, and maintain complex applications supporting comprehensive error handling.  It can be applied to any type of application, either as a whole, or just selected program components and sub-applications.

When to Use ErrHandler

It's a good idea to begin by considering appropriate use of conventional VFP error handling practices:

Each of these techniques has limitations, however, which become more apparent as applications grow in complexity.  In general, very simple programs and forms can be made reasonably robust without resorting to ErrHandler, but complex applications will probably benefit from its use.

Benefits of Using ErrHandler

ErrHandler adds a number of useful error handling capabilities to those built into VFP:

comprehensive error detection with clean, flexible error handling
ErrHandler provides generic handlers for all types of unexpected errors, including both those that trigger VFP Error events and those that generate an ON ERROR condition.  Property settings make it easy for the developer to control default error handling options for each object.  Unlike VFP's rather heavy-handed default error handler (Cancel, Ignore?), ErrHandler allows clean, localized failures that don't cause more disruption than necessary.

context-sensitive error reporting and cleanup logic
While VFP's Error Event method was a major advance over its older, less selective ON ERROR command, this still represents a fairly coarse level of context sensitivity because it applies to an object as a whole, not one of its individual methods.  ErrHandler makes it easier to distinguish the exact context where errors occur, down to a specific segment of code in a specific method.  This makes it possible to generate more informative error messages with application-specific error codes and cleanup steps.

capturing, displaying, and returning detailed error information
VFP has lots of its own error codes, messages, and assorted parameters giving the details associated with an error, along with a diverse collection of built-in functions and arguments to obtain this information.  ErrHandler establishes standardized properties and methods for easily capturing all of VFP's error details automatically, displaying error information, and returning it in a consistent way.  ErrHandler also extends VFP's error information by adding application-specific error codes and messages, for greater context sensitivity.

diagnostic tracing, secondary outputs, and logging
Besides displaying error messages, ErrHandler displays diagnostic tracing messages, which can be enabled selectively and used in a VFP runtime environment (unlike VFP's Debugger).  Developers can easily extend and customize tracing for the specific needs of their own applications.  Error and tracing messages can also be "echoed" or directed to one or more secondary outputs, including the main screen background, the Debugger's output window, and/or an ASCII text log file.  In addition, ErrHandler supports a simple API for supplying your own external logging function, which will be invoked automatically as messages occur.

additional debugging and diagnostic facilities
ErrHandler includes its own dialog for displaying error and tracing messages, with controls for manually setting diagnostic, tracing, output, and logging options.  The dialog optionally lets runtime users choose whether to Ignore, Retry, Abort, or proceed with the default program behavior.  Under the VFP Development System, users can also Suspend or Resume program execution, or invoke the VFP Debugger.

Creating an ErrHandler-Based Application

You can easily adapt an existing application or application framework to incorporate ErrHandler, or you can create an entirely new application by building on ErrHandler from the outset.  To convert an existing form or class, you should redefine it to be based on one of the ErrHandler foundation classes, instead of using VFP's corresponding base class.  If you use an application framework's class library, you may want to redefine some of its "foundation" classes as subclasses of ErrHandler foundation classes.  VFP's Class Browser makes it easy to redefine classes in many cases, and you can directly edit the VCX/VCT or SCT/SCT in those cases that are not supported via the Class Browser.

Once you have a form or class based on an ErrHandler foundation class, the following steps should be taken:

specify default values for selected error handling properties
Supply your application's name as you want it to appear in error messages via the ehp_appname property.  If you want to support target indirection, initialize the ehp_targname, ehp_targclass, and ehp_targlib properties (or you can support an explicit target object reference as an Init argument).  Set the ehp_interactive property as desired for interactive or non-interactive modes of operation.  Set ehp_diagmode = .T. to enable  diagnostic features, which will be helpful at least until you finish testing and debugging.  (Note that you can also establish diagnostic options by a more flexible indirect initialization procedure when target indirection is used, as opposed to depending on hard-coded diagnostic property settings.)

supply standard ErrHandler Init Event method logic
If you supply any application-specific code at all for the Init method, e.g. for processing arguments, be sure to incorporate the necessary logic for performing the foundation class Init logic at the beginning of this method.  For example, you could use the following prologue:

* invoke foundation class Init logic to complete preparations for handling errors
if not dodefault( )          && generic parent class Init failed - can't handle errors
    return .F.                  && failure - don't allow object to be instantiated

This will assure that the proper ErrHandler initialization steps related to target indirection are performed automatically.  (If your class' Init method accepts an explicit target object reference argument, you would pass it to dodefault in the above example.)

adjust other methods for error handling appropriate to your application
For starters, see what happens when you deliberately cause an application error.  In some cases, ErrHandler's default error handling behavior will suffice, but you probably won't be satisfied with generic error handling for common, predictable errors.  The simplest remedy may be error avoidance, such as the addition of an explicit check for a valid argument type, but error avoidance is not always feasible.  This is the point where VFP's Error event comes into play.

Instead of the usual practice of writing code in a separate Error event method, the ErrHandler approach places "error trapping" logic directly in the vicinity of the method code where errors are anticipated.  The procedure for trapping errors, illustrated below, is to surround each error-prone section with a small piece of code.  This allows the method to control its own context-specific error reporting and failure logic, instead of settling for a more global default error handling procedure.  You should not normally need to supply any code for the Error Event method, because this is handled entirely by the generic ErrHandler foundation classes.

Bear in mind that only the methods of an ErrHandler object, not those of its member objects, trigger the ErrHandler's own Error event.  For example a form based on ErrHForm may contain various controls, like command buttons, text boxes, etc.  Errors in the methods of those controls are not automatically detected by the form's Error event, but errors in the form's own methods are detected.  Thus you may want to introduce additional form-level methods to perform any error-prone logic that might otherwise have been attached directly to those controls.  By making use of the form-level Error event handler, you can avoid the need for additional error-handling logic tied to individual controls on the form.

check for proper subclassing of foundation methods
If you need to put application-specific logic into any methods for which there exists ErrHandler foundation class code, make sure you make appropriate use of DODEFAULT( ) or the equivalent.  This pertains to the Activate, Deactivate, Init, Refresh, and Unload methods.  Generally you should not make any alterations to the Error event method or the EHM_... methods when you base a form or subclass one of the ErrHandler foundation classes.

create an include file of application-specific error codes and messages
While this step is not required, it is strongly recommended as a matter of good programming practice.  By creating a separate include file of your application's error codes and messages (like errhandl.h used by ErrHandler itself), you provide both a useful piece of documentation and an easy way to maintain a well-organized system of assigning unique numerical error codes.  These macros also make it easier to deal with localization (internationalization) and global revisions simply by rebuilding.

Example of Context-Sensitive Error Reporting

The following example is from the ErrHandler Demo form, errhdemo.scx.  Here is the an excerpt of code in form-level method, ErrHCM_Run, which is invoked by clicking on the Run button:

* prepare to run the specified command line by &-macro expansion
cmd = trim(thisform.text1.value)     && put command into local mvar

* enable error trapping to catch any errors during &-macro expansion
thisform.ehm_zero()                       && clear any previous error properties
thisform.EHP_TrapErrors = .t.       && take responsibility for err checking

* execute command by &-macro expansion

* check for errors trapped via generic Error event method
thisform.EHP_TrapErrors = .f.       && relinquish err checking responsibility
if not thisform.EHP_Success          && an error was caught
    * context-specific error message including general VFP error info.
    thisform.EHM_ShowAppErr(ERRH_EC_EHCINI_RUNERR, ;
        + chr(13) + m.cmd + chr(13) ;
        + chr(13) + thisform.EHM_VFPErrmsg())

In this example, the error-prone command is the one that executes a macro-expanded command line, &cmd.  Since a user could easily enter an invalid command line and there is no way to test for such errors, the ErrHandler error-trapping mechanism is an appropriate solution.  Note the use of a macro-defined error code (ERRH_EC_EHCINI_RUNERR) and error message (ERRH_EM_EHCINI_RUNERR), which are defined in the errhandl.h include file.

By using the above approach instead of relying on a comparatively "dumb" global error handler, a much more informative error message can be produced, in this case including the value of the offending memory variable, m.cmd..  If it had been left it to VFP's default error handler, the user would be told only that the command line which failed was "&cmd".  Giving more detailed, context-sensitive error messages makes it much easier to debug unexpected program behavior.

Example of Selective Tracing

Besides error reporting, the EHM_ShowAppErr method can also be used to generate diagnostic tracing messages, where the error code argument is 0.  The following is another example from the ErrHandler Demo form.  This is the code in the Run button's Click method, which invokes the method in the preceding example:

* invoke a form-level method in order to make use of the form's Error event
thisform.ErrHCM_Run         && pass the job along to method of the form

* support optional diagnostic tracing
if thisform.ehp_tracelevel > 0 ;
  and (thisform.ehp_tracelevel % ERRH_TRACEDEMO_ALL = 0)
    thisform.EHM_ShowAppErr(0, ;
      "Right after invocation of ErrHCM_Run." ;
      + chr(13) + 'ehp_success = ' + iif(thisform.ehp_success, '.T.','.F.') ;
      + ', ehp_aborted = ' + iif(thisform.ehp_aborted, '.T.','.F.'))

The diagnostic tracing logic follows a call to the form-level method, ErrHCM_Run, which supports the Run command.  If the current trace level, ehp_tracelevel, is non-zero and evenly divisible by a reserved code, ERRH_TRACEDEMO_ALL (macro defined in errhandl.h), then a tracing message displays the values of the ehp_success and ehp_aborted properties.  (This piece of tracing logic confirms that anticipated errors are handled properly during the call to ErrHCM_Run.)

ErrHandler Forum


 Top | Unframe 

Copyright 2000 - 2002, SpaceTime Systems