2

好的 - 这是一个非常奇怪的场景,我在试图深入了解它时遇到了问题。

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

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

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

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

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

App1 似乎看不到文本文件。我收到一条回复说“找不到指定的文件”。奇怪的。

我通过添加进行了调试:

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

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

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

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

感谢您抽出宝贵时间 - 如果您需要其他任何东西,请告诉我!

4

2 回答 2

5

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

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

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

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

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

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

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

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

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

于 2013-08-13T18:44:37.993 回答
3

lpDirectory函数的可选参数ShellExecute允许客户端指定要执行的程序的工作目录。

于 2013-08-13T18:18:48.343 回答