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


#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)


            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


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



            DO CASE

            CASE nRet=3 &&Abort


            CASE nRet=4 &&Retry


            CASE nRet=5 &&Ignore



      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)


                  IF BITAND(DF_NSELOGFILE,g_debugflags)>0 OR fForce













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()+"…


  2. Malcolm Greene says:


    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,


  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.