Preliminary Notes About the ErrHandl (Error Handler) Application By M. Asherman, 1/13/2000 Intro: The ErrHandl application consists of some generic foundation error-handling classes and a simple, self-contained demo form. This includes the following components: - a foundation class, ErrHandler, for deriving subclasses based on the Custom class - a foundation class, ErrHForm, for deriving subclasses based on the Form class - a collection of ERRH... foundation UDFs to support both of the above classes - a demo form, ErrHandl.SCX, based on class ErrHForm - a wrapper function, ErrHandl.PRG/FXP/APP, for the above demo form To test out the demo application, issue the following command: ? errhandl() This will launch a modal form that you can use to run any VFP command line. Try it out, including an example of an invalid command. Also note that when you exit from this form, the PUBLIC memory variable m.erh will point to an ErrHandler object containing detailed error information, even though the form no longer exists. The errhandl() demo application supports 2 optional arguments, and action code and a command line. For example, if you issue the following command: ? errhandl('run', 'phony command line') This will execute the (invalid) command line "phony command line" in non-interactive mode, causing an error message to be displayed. The errhandl.scx form is invoked, but you don't see the form itself it in this mode. See errhandl.prg for additional notes about action arguments supported, which include Prompt, PromptN, Run, and RunN. These cover the interactive/non-interactive and modal/modeless variations. Currently available documentation: - brief descriptions have been attached to all files in ErrHandl.pjx - all programs are liberally commented Misc outstanding related issues and tasks (* indicates it can wait): (see further subheadings below) Outstanding Saver-related error handling issues and tasks: - consider how to handle errors in various Saver subclasses The foundation Saver class should probably be redefined to be based on the foundation ErrHandler class. Further analysis will be required to figure out how this will then interact with forms based on the foundation ErrHForm class. - make provisions for suppressing state-saving on abnormal terminations - figure out out to handle or avoid 1-time errors on restoration of old states I.e. we need to support a mechanism for converting old configurations, which currently depends on Ignoring errors encountered during state restoration. - apply new error-handling form and Saver class(es) to btcrit and xformdbf *- create a Saver-based version of errhandl.scx As a general convenience, esp. as we add resizing, or more bells and whistles. Also this will be helpful in preparation for more complex cases, specifically btcrit and xformdbf. This really should become the basis for a new Saver demo application, maybe under a separate appl subdirectory (RunCmd). *- apply new error-handling form and Saver class(es) Saver demo application Maybe should redo the Saver demo app. to illustrate itself against instances of the errhandl.scx form, instead of its present artifical demo form. *- maybe reserve ehp_... property(ies) for support of Saver-related results I.e. a way to return the Saver functionid that was last used. We don't need to introduce any actual saver-dependencies in ErrHandler foundation class, but it would be convenient to make this small provision for returning Saver info from modal forms by tagging along with error info. Hold off on this since BT no longer requires a mechanism to return the final configuration's functionid. Outstanding issues and tasks pertaining to foundation ERRH... UDFs: - provide a hook for flexible application-specific error-handling logic E.g. add a property that holds an expression to evaluate when an error is trapped. This could be used for an application-specific error logging and severity determination function, whose result would indicate whether to allow processing to continue normally. Of importance to xformdbf. - add convenient developer features to foundation err-handling classes & UDFs I.e. support an optional developer mode, which would present a dialog with choices as to how to proceed, where the non-developer mode simply displays an error message. Developer choices might include Fail (default), Ignore, Debug, Cancel, Quit, etc. - consider switching data sessions in errhtarg.prg auto-allocation logic To avoid the problem of residual data sessions. Not yet clear this is important enough to justify the risk of subtle problems associated with changing data sessions. Residual data sessions can also be avoided by pre-allocating external target error handlers, so it's not an urgent problem. *- support additional expansion of error info obtained from AERROR() *- support an optional error logging facility *- maybe should support an expression for name of indirect target errhandler For greater flexibility over present ehp_targname mechanism. Cost is not an issue here, since it normally gets evaluated only once. Hold off on this until clear need arises. Outstanding issues and tasks pertaining to ErrHForm foundation class: *- support optional blanket error-handling coverage for a form Maybe use an ON ERROR handler that takes over when form is active, and restores the prior ON ERROR handler upon form deactivation. Review Doug Hennig's stuff and FFC for similar gimmicks. This can wait until after we have made a first pass at incorporating explicit error-handling facilities into btcrit and xformdbf. Outstanding issues and tasks pertaining to ErrHandler foundation class: (nothing currently outstanding under this heading) Outstanding issues and tasks pertaining to ErrHandl.SCX/PRG (demo programs): *- let errhandl...Run method take a command line argument and return success flag So it can be used externally, e.g. for RunN mode. *- demonstrate how to handle too-many-arg errors This could be done by declaring additional dummy arguments, I suppose, but it hardly seems worth the effort just to prove the point. Otherwise, we need to rely on the catch-all ON ERROR mechanism to handle such errors. *- support an optional errhandl() arg for supplying an explicit target errhandler To demonstrate an even greater degree of convenience and flexibility in obtaining error information. Wait and see if this feature is ever needed. *- errhandl.scx could also serve as a useful generic VFP command processor Although originally created purely for testing and development of error-handling, this is really a useful general-purpose utility in its own right. Also could serve as a replacement for my old BENCH dialog, simply by the addition of some timing/benchmarking statistics. *- allow for a variable number of multi-step command line args to errhandl.scx/prg So these should go last. *- create versions of generic DOCMD/IFCMD.PRG that include similar error-handling DoCmd() could be implemented as wrapper for non-interactive ErrHandl.scx to accomplish this, at least in theory. We may want to avoid imposing error-handling cost and complexity in some cases, however, so keep these versions separate. General guidelines and conventions: @- rebuild and test dependent apps after any changes to foundation errhandler classes This currently includes Querier, and more to follw shortly. @- use negative error codes for foundation classes, as opposed to app-specific errors @- any place that explicitly fails should report the reason, if possible @- all error reporting should use standard, approved methods @- make provisions for handling any common, easily encountered errors @- maintain clean copies of selected files in shared mdacomm directory Only copy selected files that may be directly used by other apps. Don't copy files used only internally within the app. For errhandl, the files to be copied into mdacomm are: errhandl.h/txt/vcx/vct, and various errh*.fxp foundation UDFs. Also note that errhandl.app is a generic tool, and this may also be copied into mdacomm, but don't copy the wrapper, errhandl.fxp/prg (which is NOT a foundation UDF). @- avoid unnecessary direct cross-app dependencies by making use of mdacomm @- all apps should avoid potential name conflicts in case moved into mdacomm E.g. avoid file names like "notes.txt" in favor of ".txt". @- add comments in history of each app as to when last uploaded to BT server Change history: 991106 introduce new generic error-handling class, ErrHandler, suitable for querier I looked at VFP's FFC _error class, and also some examples of error-handling logic used by Doug Hennig, based on Stonefield's framework. Neither of those approaches is simple enough nor are they adequately documented and commented for me to feel comfortable with them. So I created a simple, modular, custom ErrHandler class in mdacomm\errhandl.vcx, which I will use for diverse MDA apps. 991107 shift error reporting method from Querier into generic ErrHandler With a little adjustment we should be able to turn this into a generic piece of logic, thereby leveraging this feature across all ErrHandler subclasses. Also eliminate obsolete error-related properties we added to Querier, since these are now replaced by ErrHandler properties. 991107 include VFP error info captured via program() and sys(16) 991107 add blank lines between sections of long error messages For better readability and easier distinction between app-specific and generic VFP parts. 991107 supply a title for messagebox error reporting cases I guess a reasonable default would display the methodname and the application-specific error #. Custom property(ies) could be used to override this, e.g. to substitute "Querier" or "Querier.QueryCommand" for the default of "Querycommand". Try this: introduce new ehp_appname property, which picks up method name as the default. We may as well always display the application-specific error # in the window title, since we don't display it elsewhere. 991107 allow for a default prefix to be added to WAIT WINDOW messages I.e. provide ErrHandler property(ies) to do this automatically, as an option, just as there is some way of constructing a default messagebox title. 991107 may as well throw in an option as to type of messagebox to be used Based on new property, ErrHandler.ehp_messageboxtype. 991107 include clearing of status bar text in ErrHandler.ehp_apperrcode logic This would eliminate the need for lots of scattered SET MESSAGE TO commands that usually follow error messages. Double-check that this is always ok - seems ok for all current querier usage. Remove redundant SET MESSAGE TO commands from querier.querycommand method. We could add a property to ErrHandler to make this behavior optional if necessary, but wait and see if needed. 991108 **** UPLOADED CHANGES TO BT SERVER'S D:\REDP\APPL\MDACOMM\ **** 991117 introduce the new appl\ErrHandl subdirectory, project, etc. The first version delivered to BT consisted only of a class library in mdacomm. Since we're beefing up this facility, give it its own modular application directory. 991117 introduce foundation class, ErrHForm, for error-handling forms Which will ultimately be used as the basis for revised BTCrit and XFormDBF. 991117 create demo form, ErrHandl.scx to illustrate form-based error-handling This should cover both modal and modeless cases, as well as interactive/non-interactive modes. Let the demo form provide a way to run a VFP command line under its control. In order to create a form (.scx) based on a class other than VFP's Form class, use the following syntax: CREATE FORM errhandl AS ErrHForm FROM errhandl 991120 demo form Init arguments for specifying run mode and an initial command line Support interactive and non-interactive, modal and non-modal cases. 991120 return value for modal cases - requires Unload event logic, etc. Add new errhform.ehfp_returnval property to support this. Note that Unload event no longer has access to member objects, because they have already been destroyed by the time Unload fires. 991120 use ACTIVATE SCREEN to avoid garbage output into form for modeless cases The form's Deactivate event seems to be the main place to do this, but I also needed this in form Refresh to cover the initial case. Maybe there's a cleaner solution, but this will do for starters. 991120 create preliminary wrapper function, errhandl.prg, for form errhandl.scx Just a convenient function interface with appropriate defaults that allow it to be generally useful. Try to return a correct success flag in all cases. 991122 provide a generic mechanism for returning error info from a dialog form E.g. where the dialog returns a success flag only, but there is some way to get to all additional error details, even though the form is gone. The main issue is to provide a mechanism for connecting to an external errhandler object. This also would be useful for communicating with modeless forms. 991122 return default errhandl.scx error info in _screen.errhandler It would be helpful if there also existed a simple way to override the default choice of error handler, e.g. by supplying an additional optional argument, but a default external handler will do for now. 991122 support automatic alloc of public mvar or _screen member for indirected cases 991122 use macros to avoid scattered refs to hard-wired name "errhandler" 991123 create generic error-handling properties for errhform Exactly like the custom properties of errhandler class, so that a common set of error-handling UDFs can operate against either class. These properties all begin with "ehp_". Don't forget to set default values via property sheet. 991123 interactive/non-interactive should be an errhform property 991123 errhform-level property and/or method for enabling/disabling error trapping 991123 create generic error-handling UDFs usable in both errhandler and errhform To avoid redundancy in corresponding methods of different foundation classes. New UDFs, errhshow/errhvfms will need to be maintained in mdacomm, since they are referenced by errhandl.vcx. 991123 create generic error-handling methods of errhform Corresponding to those of errhandler class, with the same arguments. These methods all begin with "ehm_". Specifically, EHM_ShowAppErr and EHM_VFPErrMsg. 991124 rename previous ehfp_... properties to ehp_..., if these are to be retained Another aspect of greater symmetry - these properties could just as well be supported for other base classes. 991124 new errhandler/errhform method, ehm_zero, to clear error info Plus associated UDF, errhzero.prg, which should support optional indirection. 991124 may as well make an initial call to ehm_zero(this) in errhform.Init So that we don't need to assign these inits via property sheet for each base class. 991124 watch out for special situations where internal errhandler is missing As in the Unload event. Better still - rely only on form-level properties and methods, so this is no longer a source of potential problems. 991124 avoid casual slinging around of refs to property ehp_targobj These really should be used only internally in foundation class methods or supporting errh... UDFs. 991124 overhaul errhform class for greater symmetry with errhandler class Error-handling foundation classes should have a common set of ehp_... properties and ehm_... methods. If VFP allowed us to derive different base class types from a common ancestor, we wouldn't have needed this redundancy, but with suitable shared UDFs it's not a big deal. 991125 break out logic to initialize ehp_targobj from errhform.init Use new UDF, errhtarg.prg, to do the work. This UDF should be applicable to both ErrHForm and ErrHandler classes. We could also add a corresponding ehm_... method for this, but wait and see, since this is currently used in only one place. 991125 add ehp_... properties for target classname and classlib name To be used in for auto-creation logic for getting object reference to indirection target. This is much more flexible than using macro constants. 991126 clean up error handling within errhform itself and its support UDFs Notably errhtarg.prg, which should use approved error detection and reporting techniques. Also provide corresponding macro-based error codes and messages. 991126 support mechanism for dynamic init of targobj, i.e. not just auto-init This can now be accomplished by simply setting the ehp_targobj property, as well as by using the errhtarg() UDF for additional features. 991126 remove obsolete errhandler member from foundation errhform class New architecture eliminates the need for this, because we now have ehp_... properties and ehm_... methods directly attached to the form. 991126 check for errors in PUBLIC declaration statement in errhtarg.prg Since this error could easily be caused by supplying an invalid mvar name in property ehp_targname. 991126 fix ErrHandl.prg to avoid bombing on numeric Action arg As well as any other form of invalid arg errors. Let ErrHandl.scx handle all error cases. 991126 demonstrate proper error reporting for invalid action case in errhandl.Init 991126 make a cleanup pass over ErrHandl.scx/prg To demonstrate proper error-handling conventions at least for all error cases detected. 991127 remove obsolete macros made unnecessary by more flexible ehp_... properties This also means we no longer need to include errhandl.h in class errhform, but we still need to use this include file with errhtarg.prg. However, we don't need to copy errhand.h into mdacomm if we only put errhtarg.fxp in mdacomm (i.e. no need to copy the PRG). On the other hand, we may as well put errhandl.h into mdacomm for the benefit of any apps that may want to sort out error codes. 991129 errhform.deactivate: do activate screen to avoid annoying modeless cruft This logic really belongs in foundation errhform class, since it's really a pretty generic issue with modeless forms. This avoids the need to put this logic in individual forms like errhandl.scx, xformdbf.scx, and btcrit.scx (once we redefine it as an ErrHForm). 991129 supply generic ErrHForm.Refresh logic For forcing termination in "non-interactive" modes, and avoidance of annoying screen output misdirected into modeless form window. 991129 let generic ErrHForm.Unload include a SET MESSAGE TO step Since this is generally preferred, e.g. in btcit and xformdbf, and it could easily be overridden if desired. This is also consistent with generic errhshow.prg logic. 991203 rework errhandler class to use common UDFs shared by errhform Also need to add ehp_targ... properties, for symmetry, so that shared UDFs will work. Add method ehm_zero, too. 991203 add support for indirection at the foundation errhandler level I.e. add properties to class errhandler, which would include the name of the global mvar or _screen member for extra target errhandler. This is more general than restricting support of indirection to the errhform class. Since foundation UDFs do the work for us, there is no additional effort required to achieve this greater symmetry with class errhform. 991203 **** UPLOADED CHANGES TO BT SERVER'S D:\REDP\APPL\ERRHANDL\ & ...MDACOMM\****