Application logging and Error methods


I have some Fox classes that run in several modes.



  • The normal fox interactive design environment
  • In a runtime Multithreaded DLL from the fox interactive environment
  • In a runtime Multithreaded DLL from within a client application (like windows explorer)

 


The error methods of those classes do different things depending on _vfp.StartMode(“Returns the Fox Start Mode. 0=None, 1=LocalServer, 2=Runtime EXE Server, 3=Runtime DLL Server, 4=VFP Runtime App, 5=Runtime MTDLL Server”)


 


VFP MT DLLs do not normally do UI (User Interface) because they’re targeted to be used in server applications, such as web servers which have no UI. But you can still call MessageBox by using DECLARE DLL as shown.


 


Many windows APIs that take strings as parameters have two versions: ANSI and Wide char. The ANSI ones use a single byte per character, and the Wide versions use Unicode. If you single step through the assembly code you can see that one version just converts the parameter for the other and then calls it.


 


From winuser.h:


 


#ifdef UNICODE


#define MessageBox  MessageBoxW


#else


#define MessageBox  MessageBoxA


#endif // !UNICODE


 


You can see that both MessageBoxA and MessageBoxW are exported from user32.dll:


link /dump /exports c:\windows\system32\user32.dll


 


The OutputDebugString call outputs to any attached debugger. I typically run with Visual Studio as the debugger, so its output window shows a log of what’s happening.


 


The VFP program has a single PUBLIC integer variable called g_debugFlags which has up to 32 bits, each of which can indicate which things to log to the DebugOutputWindow and/or a logfile. Filtering the events to only those of interest reduces the noise.


 


I have both a RETRY and a RETURN statement: while at a breakpoint in the VFP debugger, I can change variable values or switch to the command window to open tables, etc. A RETRY will try again to execute the erroneous statement, and RETURN will skip that statement and proceed with the following one.


 


 


 


DEFINE CLASS ShellNode AS session


      PROCEDURE error(nError, cMethod, nLine)


            cStr=PROGRAM()+" "+MESSAGE()+" "+MESSAGE(1)+" "+TRANSFORM(nError)+" "+TRANSFORM(cMethod)+" "+TRANSFORM(nLine)


            ?cStr


            IF _vfp.StartMode=0


                  SET STEP ON && open debugger


                  RETRY && to retry statement that triggered err


                  RETURN && SET NEXT Stmt (Shift+Ctrl-F7 here will skip statement that triggered err


            ENDIF


            DECLARE integer MessageBoxA IN WIN32API integer,string,string,integer


            this.logit(cStr,.t.)


            nRet=MessageBoxA(0,cStr,PROGRAM(),2+512+32)


            DO CASE


            CASE nRet=3 &&Abort


                  COMRETURNERROR(PROGRAM(),cStr)


            CASE nRet=4 &&Retry


                  RETRY


            CASE nRet=5 &&Ignore


                  RETURN


            ENDCASE


      PROCEDURE logit(cstr as String,fForce as Boolean)


            IF BITAND(DF_NSELOGFILE + DF_NSEVFP,g_debugflags)>0 OR fForce


                  DECLARE integer OutputDebugString IN WIN32API string


                  cstr=TRANSFORM(DATETIME())+" "+cstr+CHR(13)


                  OutputDebugString(cstr)


                  IF BITAND(DF_NSELOGFILE,g_debugflags)>0 OR fForce


                        STRTOFILE(cstr,LOGFILE,.t.)


                  ENDIF


            ENDIF


ENDDEFINE


 


 


 


63067


 


 


 


 

Comments (3)

  1. Stefan Wuebbe says:

    Another great article, thanks!

    On a probably less-important side aspect – is there a "hidden insight" in not declaring variables like cStr, nRet as Local at that point?

    > PROCEDURE error(nError, cMethod, nLine)

    > cStr=PROGRAM()+" "+MESSAGE()+"…

    -Stefan

  2. Malcolm Greene says:

    Calvin,

    Thanks for continuing to post code examples. Every post is a learning experience for me and most of your code posts find their way into my code base almost immediately.

    The FOX Rocks!

    Thanks for an awesome product,

    Malcolm

  3. Pasan says:

    Is there any way to get the error line code at runtime.VFP help says message(1) is not available at Runtime.

Skip to main content