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 gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Using Project on different PC's with different Drive Letters 4

Status
Not open for further replies.

David Higgs

Programmer
May 6, 2012
392
GB
During Program Development I often use my "Project" on Drive D: of my Desktop PC. I also use my "Project" on my Laptop on Drive C: To allow for this I have the following code in the Main PRG of my application:

Code:
selected_drive = LEFT (SYS(16),3)	&& Executing Program Filename
CD (selected_drive)

The above appears to work, but is this correct?

Would the compiled .exe work with this setup?

How do others deal with this scenario?


Regards,
David
 
When you say that you use your "Project" I assume that you mean the VFP Development Project.

If so, then the only thing that it, itself, needs is to be able to find the various files associated with its application. And to do that it generally uses the mapped drive letters to find the files.

However if, by "Project", you mean the Application (the compiled .exe) created by the VFP Project, then that is something different.
The Application needs to be able to be able to 'find' and access other application-specific "items" like Data Tables, Image files, Files to Import, etc. and if the location ('pathing') to those include include mapped drive letters and if those mapped drive letters are not accurate on the alternate installation, then the application will not run properly.

There are various ways to get around this, but it most certainly needs to be taken into consideration.

Good Luck,
JRB-Bldr


 
David,

Your project has got nothing to do with how your compiled EXE finds the files it needs at runtime (I'm assuming you mean your VFP project - the one you see when you open a PJX file in the development environment - as per JRB's post above.)

As far as forms, reports, classes, PRGs, etc. are concerned, these will normally be bound into the EXE (except any that you explicitly choose to exclude), so there will be no problem in the EXE finding them. Other files - mainly data files, but possibly also images or text files such as INI files - are a different matter. In those cases, you will need some way of determining where the files are stored, and communicating that to the program. There are many ways of doing that, but in general they have nothing to do with the project.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
And to answer the second part of your question:

How do others deal with this scenario?

I do almost exactly what you do, except that I also allow for moving to a different directory as well as to a different drive:

Code:
SET DEFAULT TO JUSTPATH(SYS(16))

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I might suggest that you take this possibility into consideration in a number of ways.
NOTE - this suggestion is just ONE way among MANY others.

1. Create your data & file 'architecture' in such as way that it is easily referenced in a Relative manner from a single 'starting' directory. Where all other needed files are in sub-directories 'under' the "Primary File Location"
Example:
<Primary File Location>​
<Data Directory>​
<Image Directory>​
<Etc.>​

2. Now your Installation routine (or initial execution configuration routine) can define the "Primary File Location" and store this in some manner (into a Config.dbf or the Registry, etc.)

3. Now all of your needed files, data tables, etc. can be referenced in your application Relative to your single "Primary File Location"

4. Then when your application launches it reads the "Primary File Location" from the stored location and can then 'find' everything else Relative to that.

Good Luck,
JRB-Bldr


 
David,

I agree with everything JRB just said.

In addition, you said at the outset that you need to move the project from Drive D on one machine to Drive C on another. In that case, you don't need to execute the code that you posted. When you move a project, and then open it in the development environment, VFP will ask "Do you want to make xxx the new home directory?". If you answer Yes, all the files within the project will be correctly found.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I also CD at runtime, but just because I work with some files within the EXE directory, eg just creating a debug.txt file aside of the app.exe results in some log outputs and messages normally not of interest.
So in general it's a good practice to CD into the project home. Don't just move to the drive.

I normally use SYS(16,0), as that is the start file location, no matter where it is executed. There is just one slight problem, in main.prg being in some subfolder relative to the PJX, so I asjust that. At design time I could also use _VFP.ActiveProject.Name as path to the PJX, but then the start of main.prg can't be done without the project open from command window and situations with two open PJX files also don't allow that.

When your EXE runs, you may need to find some relatively located files, which are also external at runtime, for internal files paths don't matter, as files are first searched within the EXE, but I also remember situations where I got a OS message to insert a Disc into a CD-ROM Drive D: because my design time project was at drive D: and there it wasn't a CD-ROM drive (obviously you don't develop on CD-ROM, not even on CD-RW).

You can also decide depending on _VFP.Startmode, I now tend to also work in projects, where you need to first set a certain default path before starting main.prg, as there is no such automatism. It's possible to get used to that and it also has happened compiling only worked in regard of loading header (.h) include files, if you change into the right directory before a build and so that habit has a plus in that respect, too.

Besides all that quirky things I think everybody encountered sometimes, VFPs way to look for files in an EXE first anyway make directory changes at runtime obsolete, unless you want to address files in or relative to the EXE directory and when you don't want users to be able to break this by defining a Working Directory in a shortcut to your EXE. Because that is really changing VFPs start default directory and breaking simple checks as [tt]If File("debug.txt")[/tt]. Enabling user to configure some working directory should rather be done by some configuration data´instead of shortcut properties.

Bye. Olaf.

 
One problem that I have with using the location of the EXE approach is that my client's application EXE's are most often installed on the individual workstations for easier maintenance and better execution (launched from a 'starter' similar to: An Application starter (with auto copy from server into local station). faq184-4492)

From there the application accesses 'exterior' items like Data Tables, etc. which are physically located on a centralized server which is generally 'seen' as a mapped drive.

If that mapped drive needs to change I have its setting (Drive Letter or UNC) saved off.
Then when the application launches it retrieves this "Home" configuration setting and then can 'find' these other application essentials and work as needed.

Good Luck,
JRB-Bldr


 
And what is the problem in that? The location on every individual workstateion could even differ, if you determine SYS(16,0). You might also try _VFP.Servername, though I always have the feeling this is only working for automation servers started as such. I have seen it pointing to the vfp9 runtime, too. SYS(16,0) is really reliable in the aspect of giving you the EXE name, when running in an EXE, it only may give you nothing (ie executed from command window) or a subfolder (ie when used in main.prg). One way is of course to put main.prg parallel to the pjx, despite it should go into a prgs subfolder.

Bye, Olaf.
 
I've never really used SYS(16) so maybe I am mis-understanding it.
But VFP Help indicates that SYS(16) would return the "Executing program file name".

So if the "Executing program" was resident on the local workstation (somewhere on a locally defined drive such as C:, D:, etc.), then it would not help in finding those files, etc. on the 'external' mapped drives that are in fact somewhere on an 'external' Server ((maybe mapped as drive F: or G: or "\\DataServer", etc.).

So if the user could define and Save the <Primary File Location> (or external 'HOME' mapped drive) and the 'external' file architecture was defined as suggested above, then the other external files could readily be 'found' as Relative to the <Primary File Location>

Good Luck,
JRB-Bldr
 
Well, there is a second parameter. Simply see what a 0 means.

Even without it, if you determine SYS(16) in main.prg it has the same effect there as SYS(16,0) anywhere later and you can save the result in a goApp property, for example. Also notice, it differs for usage in PRG and SCX or VCX code and it differs in IDE vs EXE. Make same tests in IDE and a built EXE with Messageboxes or logging to a txt file.

Bye, Olaf.
 
I just did that for you:

[pre]in IDE:
main.prg Sys(16) |C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16\PRGS\MAIN.FXP
main.prg Sys(16,0) |C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16\PRGS\MAIN.FXP
myapp INIT Sys(16) |PROCEDURE MYAPP.INIT C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16\LIBS\SYSTEM.VCT
myapp INIT Sys(16,0)|C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16\PRGS\MAIN.FXP

in EXE:
main.prg Sys(16) |C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16\HERE.EXE
main.prg Sys(16,0) |C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16\HERE.EXE
myapp INIT Sys(16) |PROCEDURE MYAPP.INIT C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16\LIBS\SYSTEM.VCT
myapp INIT Sys(16,0)|C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16\HERE.EXE[/pre]

The file composition of my little Here.PJX test project can be read from this test output. Just notice myapp is a class within the system.vcx I instanciate as goApp. All output after | is from the SYS function described before the |.

The diversity of output can be coped with by either doing SYS(16) in main.prg only and saving the result in a globally available property or at any later stage doing SYS(16,0), as the main.fxp is always on the stack, that result is constant throughout the whole app lifeycycle and called from any place.

Removing the pain of the PROCEDURE part before the output path by doing SYS(16,0) only we get to:

[pre]in IDE:
main.prg Sys(16,0) |C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16\PRGS\MAIN.FXP
myapp INIT Sys(16,0)|C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16\PRGS\MAIN.FXP

in EXE:
main.prg Sys(16,0) |C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16\HERE.EXE
myapp INIT Sys(16,0)|C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16\HERE.EXE[/pre]

Now we can take JUSTPATH:

[pre]in IDE:
main.prg Justpath(Sys(16,0)) |C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16\PRGS
myapp INIT Justpath(Sys(16,0))|C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16\PRGS

in EXE:
main.prg Justpath(Sys(16,0)) |C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16
myapp INIT Justpath(Sys(16,0))|C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16[/pre]

If you move your main.prg into the PJX folder:

[pre]in IDE:
main.prg Justpath(Sys(16,0)) |C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16
myapp INIT Justpath(Sys(16,0))|C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16

in EXE:
main.prg Justpath(Sys(16,0)) |C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16
myapp INIT Justpath(Sys(16,0))|C:\USERS\OLAF\DOCUMENTS\VISUAL FOXPRO PROJECTS\TESTS\SYS16[/pre]

Now all outputs are the same. The other way to keep main.prg in the prgs subfolder is removing the \PRGS part when in IDE, by doing JUSTPATH once more when _VFP.Startmode=0. The adjustment differs with where you put your main.prg in your project directory structure. So there is no general rule and code for that, but you only need to cope with it in the IDE.

In any case, David, your LEFT(SYS(16),3) done in a main.prg will always be the correct drive letter. LEFT(SYS(16,0),3) also, unless you make an SCX your main project file. But who does that? We all know the concept of a main.prg

In the end Justpath(Sys(16,0)) is very surely giving you the path of your EXE done anywhere in any code in the executable and within your IDE you may get the same path, if you decide to put your main.prg there, too, or you adjust it for that case.

Bye, Olaf.
 
The reason for starting this thread was that originally I did all my Development and running of applications on one machine and on one drive. When I moved (Project and associated files) to another machine I had problems with "File not found" etc. I traced this down to having used drive letters in my main prg, so I had to find a "future proof" solution. I thought I'd ask if I was on the right track and also to see how others approached this issue.

Mike Lewis said:
SET DEFAULT TO JUSTPATH(SYS(16))
That's interesting, I didn't realise JUSTPATH, JUSTDRIVE existed, very useful, I'll read further.

jrbbldr said:
Create your data & file 'architecture' in such as way that it is easily referenced in a Relative manner from a single 'starting' directory. Where all other needed files are in sub-directories 'under' the "Primary File Location"

Fortunately I started off in a fairly structured manner so my application follows your advice.

OlafDoschke said:
I also CD at runtime

It's nice to know I'm on the right track. Thank you for your example code etc, I will study this in detail.

Thank you everyone for all your replies and the discussions that followed, very informative.


Regards,
David
 
David said:
I traced this down to having used drive letters in my main prg,

That is clearly where you went wrong - as you now realise.

You should never hard-code drive letters or absolute directory paths in your program code. Doing so will always lead to trouble. There might be a few exceptions - such as in small one-off programming tools that no-one else will ever use - but certainly not in real commercial applications.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike Lewis said:
That is clearly where you went wrong - as you now realise.

I do indeed !

You should never hard-code drive letters or absolute directory paths in your program code.

I presume it is ok to hard-code "SET PATH" from the defined "Root Directory" ?


Regards,
David
 

I presume it is ok to hard-code "SET PATH" from the defined "Root Directory" ?

Yes, because in that case the paths would be relative, not absolute.

You might also use SET PATH with directories whose locations are stored in some external medium, such as an INI file or the Registry. That would also meet the requirement for the paths not to be hard-coded.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Yes, Mike,

and knowing a root path can be very helpful, even more so in conjunction with an application starter.

You can put some config.DBF aside the EXE in the central server store, which is copied to local stations. Then you have something at hand where you a) always find it and b) can still maintain it in one central place. You can also work with a convention a config.dbf is at some place and read every other paths to important thing frmo there, partly also, where other EXEcutables are located, if you have to cope with a bunch of applications, as I have to.

Then you might also put that one path to a config.dbf into a config.ini with the path to config.dbf and thereby even can switch between different confog.dbfs just by changing the path to them.

It looks complicated to need to read a config.ini just to know the path to a config.dbf just to read further paths of interest from that. But everything outside your EXE allows you to configure and change behavious without recompiling. You can overdo that, but the idea to look up something always means a degree of freedom, a junction point you can easily maintain, understand or explain to admins or powerusers. You can even include a way to change this userfriendly in an options section of your application, of course. Such things don't just make sense in an IDE.

Bye, Olaf.
 
It looks complicated to need to read a config.ini just to know the path to a config.dbf just to read further paths of interest from that. But everything outside your EXE allows you to configure and change behavious without recompiling.

The way I usually handle that is to have an INI file in the same directory as the executable. The INI file has settings related to the application as a whole - rather than an individual user. As well as all the relevant directory paths (data, images, archives, error logs, etc), it might store the location of the help file, address of SMTP server, and similar stuff. The application can easily find the INI file by using SYS(16) (and this has the benefit that the same code works in the development environment as well).

One advantage of using an INI file is that you can give a senior user or administrator the ability to change the relevant configuration details without reference to the developer.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top