如果应用程序在其他目录中启动父应用程序,则文件I/O无法正常工作

Con*_*ran 2 delphi file-io shellexecute delphi-xe3

好的 - 这是一个非常奇怪的场景,我在试图找到它的底部时遇到了问题.

我有2个应用程序(简单地说app1和app2)和一个文本文件(txt1).
App1和txt1位于同一目录(例如C:\ APP)中,但app2位于app1目录(C:\ APP\SUB)的子目录中.

当App1启动时,它会使用标准从txt1读取一些内容:

AssignFile(txtFile,'txt1.txt');
Reset(txtFile);
Run Code Online (Sandbox Code Playgroud)

没问题.但是,当App2通过shellexecute命令启动App1时:

shellexecute(0,'open','..\app1.exe',nil,nil,SW_SHOW);
Run Code Online (Sandbox Code Playgroud)

App1似乎无法看到文本文件.我收到回复说"无法找到指定的文件".奇.

我做了调试添加:

if not fileexists('txt1.txt') then
showMessage(ExtractFilePath(application.exename));
Run Code Online (Sandbox Code Playgroud)

这显示了app1(本身)的正确文件路径,那么,为什么'reset'命令会产生'找不到......'错误?我想知道是否使用shellexecute使应用程序以某种方式认为它是从子目录执行而不是它所在的实际目录?

我知道最简单的解决方案是简单地将文件路径添加到我的'app1'打开的每个文件的前面(我试过它,是的,它确实可以正常工作),但是,实际上有数百个这样的文件应用程序通过类似的方法访问(无论是txt,ini还是dll),即根据文件与应用程序在同一目录中分配文件,因此,不设置完全限定的文件路径,因此更改(和维护)它们一切都不是我们此时感兴趣的事情.

以前有没有人见过这样的东西?除了ShellExecute之外,还有更好的方法让App2启动App1吗?没有任何参数或任何东西可以传递给App1,我只需要它来启动.

感谢您的时间 - 请告诉我您是否需要其他任何东西!

Dav*_*nan 5

默认情况下,新进程继承父进程的工作目录.当然,您不需要使用此默认值,但您的代码会这样做.相对路径是相对于工作目录的.所以第二个进程继承了第一个进程的工作目录,因此查找错误位置的文件.

根本问题是您的程序依赖于工作目录的值.但是文本文件不在工作目录中.它与相关的可执行文件位于同一目录中.当这两个目录碰巧重合时,你很幸运.

因此,您应该停止使用相对路径,并开始使用使用可执行文件路径构造的完整绝对路径.

FileName := ExtractFilePath(ParamStr(0)) + 'txt1.txt';
Run Code Online (Sandbox Code Playgroud)

调用ShellExecute的方式存在同样的问题.同样,您依赖于工作目录.您需要使用的可执行文件名是:

ExtractFilePath(ParamStr(0)) + '..\app1.exe'
Run Code Online (Sandbox Code Playgroud)

虽然您已经接受了建议在创建新进程时指定工作目录的答案,但这是错误的解决方案.该文件与可执行文件位于同一目录中,因此您应该如何找到它.

您的代码依赖于其工作目录的方式对调用进程提出了不必要和艰苦的要求.即它们指定的工作目录与可执行文件的目录相同.您根本不应该要求您的呼叫者,尤其是因为没有必要这样做.

还要注意,对于GUI程序,工作目录在执行期间可能会发生变化.例如,当您使用文件对话框时.对于控制台应用程序,可以将工作目录视为输入参数.对于GUI程序,情况并非如此.