Question

OK - this is a very oddball scenario, and I am having problems trying to get to the bottom of it.

I have 2 applications (lets just say app1 and app2) and a text file (txt1).
App1 and txt1 reside in the same directory (say C:\APP), but app2 resides in a subdirectory of app1's directory (C:\APP\SUB).

When App1 launches, it reads some stuff from txt1 using the standard:

AssignFile(txtFile,'txt1.txt');
Reset(txtFile);

No issues with that. However, when App2 launches App1 via a shellexecute command:

shellexecute(0,'open','..\app1.exe',nil,nil,SW_SHOW);

App1 cannot seem to see the text file. I get a response saying 'Specified File Could Not Be Found'. Odd.

I did debug by adding:

if not fileexists('txt1.txt') then
showMessage(ExtractFilePath(application.exename));

And this shows the correct file path of app1 (itself), so, why then, does the 'reset' command produce the 'Could not find....' error? I am wondering if employing shellexecute is making the application somehow think it is executing from the sub-directory as opposed to the actual directory that it is in?

I understand that the easiest solution is to simply add the file path to the front of every file my 'app1' is opening (I tried it and yes, it does work correctly), however, there are in reality, hundreds of files this main application accesses through a similar method (be they txt, ini or dll's) i.e. assigning the file based on the fact it is in the same directory as the application, therefore, not setting the fully qualified file path, so changing (and maintaining) them all is not something we would be interested in doing at this time.

Has anyone ever seen something like this before? Is there a better way for me to have App2 launch App1 other than ShellExecute? There are no parameters or anything to be passed to App1, I just need it to launch.

Thanks for your time - let me know if you need anything else on this one!

Was it helpful?

Solution 2

lpDirectory optional argument of ShellExecute function allows client to specify a working directory for the program to be executed.

OTHER TIPS

By default, new processes inherit the working directory of the parent process. Of course you do not need to use this default, but your code does so. And relative paths are relative to the working directory. So the second process inherits the working directory of the first, and so looks for the files in the wrong place.

The fundamental problem is that your programs rely on the value of the working directory. But the text file is not located in the working directory. It's located in the same directory as its associated executable. You just got lucky when these two directories happened to coincide.

So you should stop using relative paths, and start using full absolute paths that are constructed using the path of the executable.

FileName := ExtractFilePath(ParamStr(0)) + 'txt1.txt';

The same problem exists in the way you call ShellExecute. Again, you rely on the working directory. The executable file name that you need to use is:

ExtractFilePath(ParamStr(0)) + '..\app1.exe'

Although you have accepted an answer that suggests specifying the working directory when creating the new process, that's the wrong solution. The file resides in the same directory as the executable, so that's how you should find it.

The way your code relies on its working directory places a needless and strenuous requirement on calling processes. Namely that they specify a working directory that is the same as the directory of the executable. You simply should not require that of your callers, not least because there is no need to do so.

Beware also that, for a GUI program, the working directory may well change during execution. For example when you use a file dialog. For a console application, the working directory can be considered an input parameter. For a GUI program, this is not the case.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top