Friday, April 10, 2020

The importance of Paths in VFP

One of the commonest problems that I see in on-line forums is related to how Visual FoxPro works with files. In this respect the project manager is both a blessing and a curse! A blessing because, as long as we work through the project manager, it handles the issues associated with finding and opening files for us. A curse because we tend to forget that VFP does require paths internally. A common question is, therefore something along these lines:

The answer is, of course, that VFP  has not been given a search path. Although I have never seen this documented formally it seems that VFP takes a pretty rigid approach when asked to find something. For example when you call a function VFP first checks the currently executing program, then other programs in memory, then the current working directory, then directories on its own search path and finally the Windows Search Path. Similarly, when looking for a unqualified table name (e.g. USE account, as opposed to USE C:\Myfiles\account.dbf) , it looks first in the currently selected directory, then along its own search path and finally along the Windows search path.
Notice that directories on its own search path are always checked before any operating system level path. The significance of this is that when you give VFP its own search path it will find files without ever having to go to the operating system path – clearly this will be much more efficient since the path need only include those places that are strictly relevant to VFP.
The Default Directory
In the absence of any other information Visual FoxPro uses the currently selected drive and directory as its 'path' and you can always restore this setting by simply issuing:
SET PATH TO
However for more sophisticated applications, and certainly for development, you will have some sort of directory structure and you should always set a proper search path to include all required directories. The first thing to do is to set the default directory and there are several ways (as usual) to do this:
·         Specify a default in the Configuration File using DEFAULT = <path to directory>
·         Set the default directly in code using SET DEFAULT TO <path to directory>
·         Change to a directory using the CD <path to directory> and issue SET PATH TO
To change the default directory interactively use: SET DEFAULT TO ( GetDir() ). (The 'CD' (or 'CHDIR') command can also be used to change both drive and directory to the specified location).
Gotcha! LOCFILE() changes the path
Note that generally using the “Get” or “Put” functions (e.g. GetDir()) does not change either the default directory or the path. The exception to this rule is an apparently un-documented (in VFP) feature of the LOCFILE() function which does add the selected directory to the VFP search path as the following code shows:

*** Clear any path
SET PATH TO
? SET( ‘path’ ) && Returns nothing
USE LOCFILE( ‘account’ )  && Locate the file
? SET( ‘path’ ) && Returns C:\Projects\Data

This behavior has been part of the language since at least FoxPro 2.6W and, interestingly, it is documented in the FP2.6W Help file where it states that:
The Open dialog can be used to locate the file.  When a file is chosen from the dialog, the file name is returned with the file's path, which is appended to the FoxPro path.
However, it appears that in creating the VFP help file the last phrase got lost and it remains missing from the help in VFP 9.0 (below) even though, as we have seen, the behavior certainly still applies:
The Open dialog box can be used to locate the file. When a file is chosen from the Open dialog box, the file name is returned with the file's path.
Using the SET PATH command
Setting the path is simplicity itself. Just issue the SET PATH command followed by a list of the directories that you wish to include. You do not need to fully qualify subdirectories – separating them with either commas or semi-colons is sufficient. The example shows a typical Visual FoxPro search path:
SET PATH TO G:\VFP90;C:\VFP90\PROJECTS\;DATA;FORMS;LIBS;PROGS;UTILS
To retrieve the current path setting you can use the SET() function (which will work with most of the Visual FoxPro SET commands) as shown below. You can assign the result directly to a variable or, as shown below, directly to the clipboard so that you can then paste the current path into a program or documentation file:
_ClipText = SET( 'PATH' )
Visual FoxPro allows the use of both UNC path names, like:
\\SERVERNAME\DIRECTORYNAME\
and allows the use of embedded spaces (when enclosed in quotation marks) in directory names like:
"..\COMMON DIRECTORY\"
However, while the latter may be allowed, I subscribe to the principle that 'although you can use embedded spaces, arsenic is quicker.' (The same, by the way, applies to file names with spaces!) While improving readability, spaces can also cause problems when trying to handle files and directories programmatically and I still feel that the best advice is to avoid them wherever possible in applications. For example, the following code works perfectly well for conventional directory names, but will fail if the selected directory contains embedded spaces:

LOCAL lcDir
lcDir = GETDIR()
IF ! EMPTY(lcDir)
  SET DEFAULT TO &lcDir
ENDIF

VFP 9.0 introduces the ADDITIVE clause to the SET PATH command to enable path fragments to be added dynamically(interestingly this is what LOCFILE() has always done anyway).
Determining the Current Settings
Fortunately, Visual FoxPro provides us with a number of functions that will help us locate where we are at any time:
·         SYS(2004) returns the directory from which Visual FoxPro was started but in a distributed run time application, this will always be the location of the runtime DLL (which is normally the appropriate version of the Windows 'System' directory)
·         HOME() returns the directory from which Visual FoxPro was started by default, but has a number of additional useful options
·         _VFP.FULLNAME accesses a property of the Visual FoxPro application object that contains the full path and file name which was used to start VFP
·         FULLPATH('') or FULLPATH( CURDIR() ) returns the full drive and directory of the current working directory (including the terminal "\")
·         SYS(5) returns the default drive (including the ':')
·         CD (only works interactively in the command window) shows the current drive and directory in the current output window – but will also change drive and directory in one single command
·         CHDIR will change to the specified Drive/Driectory (just like CD) but will not report the current status (and so does not mess up your forms)
·         CURDIR() returns just the current directory (with terminal '\') but not the drive
·         SYS(2450) introduced in VFP 8.0 controls whether an application searches internally before accessing the external search path
Setting The Path
I usually use code of the following type in my startup programs to ensure that I always have the appropriate paths set – whether running in development mode, or in a compiled EXE.

IF VERSION(2) = 0
  *** Runtime Start, VFP Startup + Current Directory + "\DATA" only
  lcPath = HOME() + ";" + ADDBS( FULLPATH( CURDIR() )) + "DATA"
ELSE
  *** Design Time startup - full development path
  lcPath = HOME() + ";" + ADDBS( FULLPATH( CURDIR() )) + ";FORMS;LIBS;DATA;PROGS;UTILS"
  *** We want asserts ON in Dev Mode
  SET ASSERTS ON
ENDIF
SET PATH TO (lcPath)

Note that this differentiates between the full paths needed for Development and the reduced path used for a runtime implementation


Published Monday, March 21, 2005 1:50 PM by andykr

No comments:

Post a Comment

Writing better code (Part 1)

Writing better code (Part 1) As we all know, Visual FoxPro provides an extremely rich and varied development environment but sometimes to...