Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Whats the best way to point to the default directory? 1

Status
Not open for further replies.

jrumbaug

Programmer
Apr 27, 2003
90
US
I'm using VFP8.0. I have just finished my first and modest VFP application. I'm having confusion over how best to define the default directory. With my old DOS apps, I would just dump everything into a folder and make a shortcut to the EXE. I can't get my VFP windows app to run unless I point to the subdirectory with SET DEFAULT TO C:\MyApp, even during development. Then I have to make the InstallWizard use the same directory. I would guess there is a better and more flexable way to do this without hard coding the path. Please point me in the right direction.

Jim Rumbaugh
 
Well there are a few things here. First you probably want to make sure that the shortcut has the correct directory path to your app in it's "start in" (I have seen this cause pathing problems if it is not correct.

Next, I would add to properties to the _screen object when you first start your app...in your main.prg or whatever is set as main for the project put something like the following:

Code:
LOCAL MyAppPath
_screen.addproperty("ClientPath","")
_screen.addproperty("DataPath","")
if _vfp.startmode = 0 && running/debugging in VFP IDE
	MyAppPath = "C:\MyApp\"
	SET DEFAULT TO (MyAppPath)
	SET PATH TO "reports;progs;libs;data;images;forms;menus"
	_screen.ClientPath = MyAppPath
	_screen.DataPath = MyAppPath + "Data\"
ELSE
	MyAppPath = ADDBS(JUSTPATH(SYS(16,0))) && where is the exe running from
	SET DEFAULT TO (MyAppPath)
	SET PATH TO "images;reports" && only if you are distributing some of this stuff with the app
	_screen.ClientPath = MyAppPath
	_screen.DataPath = MyAppPath + "Data\" && data assumed to be in a subfolder named Data
ENDIF

...now whenever you need to open a table or refer to a path you can use the _screen.datapath or _screen.clientpath properties to do it such as:

USE (_screen.datapath + "MyTable.dbf") in 0 shared

or

thisform.image1.picture = (_screen.clientpath + "Images\MyImg.bmp")

...ok, let's take it a step further by adding the ability to specify the datapath at runtime. You would want to be able to do this if the application was out on a server or somewhere that is not relative to your ClientPath. You could use an INI file or the registry to hold this information, but for the purposes of this example we'll just use FileToStr() and StrToFile() to keep it really simple:
Code:
LOCAL MyAppPath
ON SHUTDOWN Do ProperShutDown
_screen.addproperty("ClientPath","")
_screen.addproperty("DataPath","")
if _vfp.startmode = 0 && running/debugging in VFP IDE
	MyAppPath = "C:\MyApp\" && hardcoded path for development/debugging
	SET DEFAULT TO (MyAppPath)
	SET PATH TO "reports;progs;libs;data;images;forms;menus" && so application can find the necessary files/source code
	_screen.ClientPath = MyAppPath
	_screen.DataPath = MyAppPath + "Data\"
ELSE
	MyAppPath = ADDBS(JUSTPATH(SYS(16,0)))
	SET DEFAULT TO (MyAppPath)
	SET PATH TO "images;reports" && only if you are distributing some of this stuff with the app
	_screen.ClientPath = MyAppPath
	_screen.DataPath = RetrieveDataPath() && retrieve path information from data.ini file
	IF EMPTY(_screen.DataPath) && couldn't find the data path so just exit
		DO ProperShutDown
	ENDIF
ENDIF

**********************************
FUNCTION RetrieveDataPath()
**********************************
	IF FILE(_SCREEN.ClientPath + "data.ini") && do we already have a data.ini file that we can use and read from
		lcDataPath = FILETOSTR(_SCREEN.ClientPath + "data.ini")
		IF !DIRECTORY(lcDataPath)
			lcDatapath = ADDBS(GETDIR("C:\","Locate Data Directory"))
			IF EMPTY(lcDatapath)
				MESSAGEBOX("Unable to locate required data. Contact your systems administrator.",64,"DATABASE NOT FOUND")
			ELSE
				=STRTOFILE(lcDatapath,_SCREEN.ClientPath + "data.ini")
			ENDIF
		ENDIF
	ELSE && no data.ini file so let's create it
		lcDatapath = ADDBS(GETDIR("C:\","Locate Data Directory"))
		IF EMPTY(lcDatapath)
			MESSAGEBOX("Unable to locate required data. Contact your systems administrator.",64,"DATABASE NOT FOUND")
		ELSE
			= STRTOFILE(lcDatapath,_SCREEN.ClientPath + "data.ini")
		ENDIF
	ENDIF
	RETURN lcDataPath
ENDFUNC && RetrieveDataPath

**********************************
PROCEDURE ProperShutDown
**********************************
	ON SHUTDOWN
	CLEAR ALL
	CLOSE ALL
	IF _vfp.StartMode = 0
		CANCEL
	ELSE
		QUIT
	ENDIF
ENDPROC && ProperShutDown

...please note that I just wrote the code above off the top of my head and it is untested. I think it's right, looks right anyways, but my apologies for any mistakes I may have made.

That's pretty much the way I do it in most of my apps (though I've greatly simplified it for this example). It's a pretty workable way of handling paths and get around many of the problems associated with it in VFP. I think it also provides a great deal of flexibility with a minimal amount of code and hope you find it useful.

boyd.gif

 
Craig.

It looks right to me as well. But can I ask why to use FILETOSTR() for your ini file rather than reading the ini file the normal (API) way with GetPrivateProfileString?


Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
 
Mike,

You could use an INI file or the registry to hold this information, but for the purposes of this example we'll just use FileToStr() and StrToFile() to keep it really simple

Just faster and easier for the example...if it were a true INI file then I would have section(s) in it and the values beneath those...

[DATABASE]
Path=C:\MyApp\Data\


...and I would have used VFPs registry.vcx to manipulate and read the ini file (which makes use of the API you reference, among others). I Didn't want to take the extra time to put that code in for an example. That's my long answer to your question.

The short one is "I'm lazy". [smile]

boyd.gif

 
Graig
Thank you very much. I have learned many things from your example that I did not know.
1)_vfp.startmode = 0
can detect I'm developing
2)ADDBS(JUSTPATH(SYS(16,0)))
gets EXE path
3)_screen.addproperty("ClientPath","")
I learned about the _screen system variable. That it can be used to hold variable info, similar declaring a public variable.
4)GETDIR()
That function would of saved me 3 hours of development. I made my own from a list box. But I wont use mine any more. I also looked and learned about GETFILE(). I love them both.
5) StrToFile()
great function. easier than using MEM files.

I have adopted your code an it works. But soon I will start another string about how to QUIT a program. I have come up with some different questions since using ProperShutDown

Again Thanks

Jim Rumbaugh
 
Normally in my main.prg

lcDefpath = CHR(34)+SYS(5)+SYS(2003)+CHR(34)
SET DEFAULT TO &lcdefpath

then maybe pass it to a form & make a form property out of it.

the chr(34) bits are to handle paths with spaces.

It just sets the defa path to the directory the exe runs from

mrF


 
Why not just use PATH statement in CONFIG.FPW?
This allows flexibility for various clients on
networks.
Tony
 
Thanks Tondi.

I'll admit I haven't used CONFIG.FPW yet, but what I'm shooting for is a way to detect the path programatically. I'm trying to avoid any hard coded paths. I want to give the installer the choice of naming the drive and installation subdirectory. Craig pointed out that I may also want to add the flexibility of having two paths, one for program and one for data incase the data is not on the local machine.

Jim Rumbaugh
 
I use config.fpw to avoid hard coding. The program, runtime files and config file resides on local drive and path statement points to folder on server for data. For various client network scenarios, just edit the config.fpw file and you are done.
Tony
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top