Catch Your Errors in
Style
by Steve Workings
Originally published in Alpha Forum
Posted at www.workings.com
January 21, 2001
OK, how many of you out there know how to catch and handle an error in Alpha Five? (A few hands go up). Now, of those who raised their hands, how many of you regularly include full error handling routines in your applications (Most, if not all hands go down.)
This is for everyone whose hand is not in the air after both of those questions have been asked.
Take a look at pages 273-277 of the Alpha Five Professional Edition Reference. Sure, that tells you a little about errors and how to handle them, and if nothing else you should start with the basic implementation illustrated in those examples. But I want to show you what just a little bit more work can do.
Lets look at one of my very basic scripts that simply closes the parent form (the main menu in this case) and then closes Alpha Five:
error_handler:
script_play("scpAdminErrorHandler")
This isnt fancy, but it shows a standard implementation of an error handler. The difference between this script and the one in the book is that when an error occurs, a script called "scpAdminErrorHandler" will play. So, its logical to look next at the contents of that script:
error_handler:
dim global userid as c
dim shared proc as c
dim shared msg as c
tbl = table.current()
err = error_code_get()
errstr = ltrim(str(err))
msg = error_text_get(err)
table = a_db_current
form = a_form_current
mode = ltrim(str(tbl.mode_get()))
obj = this.name()
ui_msg_box("A Problem Has Occurred", "Please make note of this:" + chr(10) + chr(10) + "Code: " + errstr + chr(10) + "Descrip: " + msg + chr(10) + "Table: " + table + chr(10) + "Form: " + form + chr(10) + "Mode: " + mode + chr(10) + "Object: " + obj + chr(10) + chr(10) + "Date/Time: " + dtoc(date()) + " at " + left(time(),5) + chr(10) + chr(10) + "Suggestion: If this problem persists, please bring the information above" + chr(10) + "to the attention of the administrator." + chr(10) +chr(10) + "This information has been automatically recorded.", 48)
tbl_err =
table.open(a_db_current_path + "zzlogerror",
file_rw_shared)
tbl_err.enter_begin()
tbl_err.errtime = time()
tbl_err.errdate = date()
tbl_err.errusername = userid
tbl_err.errnumber = err
tbl_err.errdescription = msg
tbl_err.errtable = table
tbl_err.errform = form
tbl_err.errmode = mode
tbl_err.errobject = obj
tbl_err.enter_end(.t.)
tbl_err.close()
resume next
Now, this isnt as complicated as it looks. Lets break it down into its pieces:
After a few DIM statements, the script assigns values to several variables. In order, they are:
err =
error_code_get()
Gets the error code number
errstr =
ltrim(str(err))
converts the error code to a character string for later use
msg =
error_text_get(err)
gets a text message associated with the error code
table =
a_db_current
returns the name of the path and table in use at the time of the
error.
form =
a_form_current
returns the name of the current form.
mode =
ltrim(str(tbl.mode_get()))
returns the user mode (Change, Enter or View).
obj =
this.name()
returns the name of the object that contains the parent script.
OK, so now that we have this information, what shall we do with it? How about first displaying it for the user?
Thats what the really long ui_msg_box command does -- it puts all the variables into a useful and informative message for the user to see. Figure 1 is a sample message box generated by this script.
Figure 1 - The custom error message ui box.
And finally, why not record this information in a table for future reference? Thats what the final set of commands do -- they open a table called zzlogerror.dbf and enter a new record with the information weve already gathered along with the time and date of the record. Figure 2 shows the form I use to view the error log.
Figure 2 - A view of the data recorded by the error handler.
Be cautioned that this is only one of several error handling routines I use. You can see by the last line in scpAdminErrorHandler that I tell the script to resume after reporting the error. This would be a disaster in, say, an accounting function where you may not only want to stop the script but return the data to its original state before the error-containing process was run.
But put an error handling routine like this in EVERY script -- I mean every one of them. And then just wait for some user to walk up and complain loudly in front of you and your boss about how many errors hes getting. If hes wrong then you will have the hard evidence to show the boss that Mr. Loudmouth is getting far fewer problems than he proclaims. And if you use the information in the error log intelligently, youll have far fewer complaints in the first place because youll be right on top of the problems and solving them much more quickly.
###