on error handling Visual Foxpro

I'm trying to setup an error handling routine.
I have tried to set up a simple "On Error do MyerrorHandler" at the begining of my main program. Then I create a simple error condition changing the name of a VFox table to get a run time error and activate the MyErrorHandler. Nevertheless the on error code doesn't execute.
If I follow the Try Catch approach how sould I proceed.
Kind regards
Lucilia C
luciliacoelhoAsked:
Who is Participating?
 
CaptainCyrilConnect With a Mentor Founder, Software Engineer, Data ScientistCommented:
TRY CATCH is good for short trapping.

You should use
ON ERROR DO errorhandler WITH ERROR(), MESSAGE(), MESSAGE(1), PROGRAM(), PROGRAM(1), LINE(), LINE(1)

However if it is not working that means you have an ON ERROR which resets it somewhere after you initialize it. What is exactly not working?

Try to put a MESSAGEBOX in the handler. Try to put a MESSAGEBOX(ON('ERROR')) elsewhere in the code to see if the trap is still initialized.
0
 
Olaf DoschkeSoftware DeveloperCommented:
As Cyril says, you were on the right track, but somehow either you chnaged a table name your code does not work on or the on error is reset somewhere. TRY CATCH is not meant for global error handling, it's just there to catch expected errors locally.

The "MyerrorHandler" must either be a prg on it's own, you set procedure to, before on error, and that procedure must stay known throughout the lifetime of the application, it's really better to make a procudure in the main.prg file, as it's safe, it's always on the call stack.

If you ant to test your error handling simply add a line of total rubbish, like:
lcCode = "sdljfsjdgsfkghks"
&lcCode

This compiles but errors at runtime.

Or do
USE hjkshdfgkjsfhgkh

Bye, Olaf.
0
 
Olaf DoschkeSoftware DeveloperCommented:
Oh, and another very simple way to test error handling is to call ERROR 1 or any other defined Error number.

Bye, Olaf.
0
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

 
pcelbaCommented:
I am using following setup and appropriate routine - it always saves the error info into a temporary file and also to the errorlog.dbf which is later posted to the development site (this part was removed):

ON ERROR DO PrgError WITH ERROR(), SYS(16), LINENO()  && This must be at the beginning of the main program

The PrgError procedure must also be in the main program or in procedure file:
 
PROCEDURE PrgError
LPARAMETERS nError, cMethod, nLine

LOCAL lcOutFile, lcErrtext, lcAppVers, lcAppName, ldAppDate, ;
  laUsed[1], lnWarea, lnI, lnWAcount, loFormObject

lnWarea = SELECT(0)

lcOutFile = ADDBS(SYS(2023)) + SYS(2015) + '.ERR'

lcAppVers = IIF(TYPE("_screen.AppVersion")="C", _screen.AppVersion, "XXX")
lcAppName = IIF(TYPE("_screen.AppName")="C", _screen.AppName, "XXX")
ldAppDate = IIF(TYPE("_screen.AppDate")="D", _screen.AppDate, {//})

IF VARTYPE(m.gn_errCount) <> "N"
  RELEASE gn_errCount
  PUBLIC gn_errCount
  gn_errCount = 0
ENDIF

gn_errCount = m.gn_errCount + 1

TEXT TO lcErrText TEXTMERGE NOSHOW 
**********************************************************************************
<<"*"+PADC("Error log info from " + lcAppName + "  v" + lcAppVers, 80)+"*">>
**********************************************************************************
ERROR trap in  <<PROGRAM()>>   <<SYS(0)>>   <<DATETIME()>>
**********************************************************************************
Version: <<lcAppVers>>  <<ldAppDate>> 
ERROR <<nError>> in <<cMethod>>,  Line: <<nLine>> (ErrCnt <<gn_errCount>>)
<<MESSAGE()>>

Settings:
SET DATE <<SET("DATE")>>
SET CENTURY <<SET("CENTURY")>>
SET STRICTDATE TO <<SET("STRICTDATE")>>
SET COLLATE TO <<SET("COLLATE")>>
Code Page: <<CPCURRENT()>>
SET EXACT <<SET("EXACT")>>
SET ANSI <<SET("ANSI")>>
SET DATASESSION TO <<SET("DATASESSION")>>

Configuration File: (<<IIF(FILE("@:\CONFIG.FPW"), "In EXE", "On disk")>>)
<<SYS(2019)>>
Resource File: (<<SET("RESOURCE")>>)
<<SYS(2005)>>
Temporary folder: (<<LTRIM(TRANSFORM(DISKSPACE(JUSTDRIVE(SYS(2023))),'999999999999999'))>> bytes free)
<<SYS(2023)>>
Home folder: (<<LTRIM(TRANSFORM(DISKSPACE(JUSTDRIVE(HOME())),'999999999999999'))>> bytes free)
<<HOME()>>
*Data folder: (<<LTRIM(TRANSFORM(DISKSPACE(JUSTDRIVE(AppDataFolder())),'999999999999999'))>> bytes free)
*<<AppDataFolder()>>
VFP Version: (Language <<VERSION(3)>>)
<<VERSION(1)>>
OS Version:
<<OS(1) + " " + OS(5) + " " + OS(7)>>
Topmost window: <<WONTOP()>>
Active form: <<IIF(TYPE("_screen.ActiveForm.Name")= "C", _screen.ActiveForm.Name, "")>>

ENDTEXT


lcErrText = lcErrText + CHR(13)+CHR(10) + "Form list:" + CHR(13)+CHR(10)

FOR lnI = 1 TO _screen.FormCount
  loFormObject = _screen.Forms[lnI]
  lcErrText = lcErrText + loFormObject.Class + " " + loFormObject.Name + " " + ;
      IIF(TYPE("loFormObject.FormMode") = "C", loFormObject.FormMode, "") + " " + ;
      IIF(TYPE("loFormObject.ActiveControl.Name") = "C", loFormObject.ActiveControl.Name, "") + CHR(13)+CHR(10)
NEXT


lcErrText = lcErrText + CHR(13)+CHR(10) + "Workarea list:" + CHR(13)+CHR(10)

lnWAcount = AUSED(laUsed)
FOR lnI = 1 TO m.lnWAcount
  lcErrText = lcErrText + STR(laUsed[lnI, 2], 5) + " " + PADR(laUsed[lnI, 1], 40) + ;
     TRANSFORM(RECNO(laUsed[lnI, 2])) + '/' + TRANSFORM(RECCOUNT(laUsed[lnI, 2])) + " " + ;
     TRANSFORM(BOF(laUsed[lnI, 2])) + " " + TRANSFORM(EOF(laUsed[lnI, 2])) + CHR(13)+CHR(10)
NEXT

RELEASE laUsed

= STRTOFILE(lcErrText, lcOutFile)

LOCAL ARRAY laCallStack[1]
= ASTACKINFO(laCallStack)

LIST STATUS TO FILE (lcOutFile) ADDITIVE NOCONSOLE
LIST MEMORY TO FILE (lcOutFile) ADDITIVE NOCONSOLE
LIST OBJECTS TO FILE (lcOutFile) ADDITIVE NOCONSOLE

LOCAL lnErrId, loErrRec

*-- Save error info into a table if possible
IF VARTYPE(gc_site_code) = 'C' AND !EMPTY(m.gc_site_code)
  TRY
    IF USED("ERRORLOG") OR OpenTable("ERRORLOG", .F., .T., "ERRORLOG")
      IF USED("COUNTERS") OR OpenTable("COUNTERS", .F., .T., "COUNTERS")
        lnErrId = CreateNewPK("ERRORLOGID")
        USE IN SELECT("COUNTERS")
        IF m.lnErrId > 0
          SELECT ERRORLOG
          SCATTER MEMO NAME loErrRec BLANK
          loErrRec.Id = m.lnErrId
          loErrRec.LogInfo = FILETOSTR(lcOutFile)
          UpdateSystemColumns(loErrRec, .T.)
          IF FLOCK()
            INSERT INTO ERRORLOG FROM NAME loErrRec
          ENDIF
        ENDIF
      ENDIF
      USE IN SELECT("ERRORLOG")
    ENDIF
  CATCH
    USE IN SELECT("COUNTERS")
    USE IN SELECT("ERRORLOG")
  ENDTRY
  
  SELECT (lnWarea)
  
ENDIF

WAIT WINDOW "ERROR INFORMATION WAS RECORDED IN " + lcOutFile TIMEOUT 1

IF m.gn_errCount > 20
  ON ERROR CANCEL
  CLEAR EVENTS
  IF VERSION(2) = 0
    QUIT
  ELSE
    SUSPEND
  ENDIF
ENDIF

Open in new window

Disadvantage of this error procedure could be an automatic program continuation after the error occurence. It can cause unpredictable results sometimes but it ignores minor errors which do not affect program run in most of the cases. You may add some dialog to PrgError to let users decide if they want to continue or not. I am testing gn_errCount in regular code which allows to make this decision automatically.

I am using TRY - CATCH for "local error handling" but to use this structure as the global error handler should also be possible.

ON ERROR setting cannot be ignored in your code, so if an error occurs it must pass the program flow into the error routine.
0
 
Olaf DoschkeSoftware DeveloperCommented:
Try RETURN or RETRY from within a Catch Block. It's not supported.

With these last lines of your error handler, you can debug when an error occurred and return to the line of error:

If _vfp.startmode=0
   set step on
   return
Endif

This is not possible from CATCH, so TRY .. CATCH is bad for global error handling alone because of that.

Bye, Olaf.
0
 
luciliacoelhoAuthor Commented:
In fact when I tried to use directly the error message and send to the screen through a MessageBox, directly. The MyErrorHandling routine didn't work at all. The workaround I used was the following: The data gathered from an error is firstly writen in a errorlog table then I use this data to interact with the user.
0
 
CaptainCyrilFounder, Software Engineer, Data ScientistCommented:
It seems that the variables you were using are local to a certain procedure/function. It's best errors are logged in a database or text file. I also send them by email to the development team of course with the permission of the user.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.