C++ Builder ExeName & ParamStr(0) 与相对最终输出目录设置

C++Builder ExeName & ParamStr(0) with relative Final output directory setting

提问人:Mark Di Val 提问时间:8/26/2022 最后编辑:Mark Di Val 更新时间:8/26/2022 访问量:83

问:

我编写了一个测试应用程序来调查将最终输出目录设置为 Application->ExeName 和 ParamStr(0) 上项目文件目录树之外的位置的影响。

我观察到的情况如下。

如果最终输出目录是相对路径(默认值为 .\$(Platform)\$(Config)),则会将其追加到项目文件路径。

对于我的测试项目文件: C:\Project\Suite\Project1\Project1.cbproj 这将导致 ExeName & ParamStr(0) = C:\Project\Suite\Project1\.\Win32\Debug\Project1.exe。

同样,这是在调试器下。选择“运行(不调试)”或在 IDE 外部运行,这两个都将具有正确的值:C:\Project\Suite\Project1\Win32\Debug\Project1.exe。

如果我将最终输出目录设置为: ..\target\$(平台)\$(配置) 要将 exe 放在以下目录中, C:\Project\Suite\Target\Win32\Debug ExeName 和 ParamStr(0) 的结果值 = C:\Project\Suite\Project1\.\..\Win32\Debug\Project1.exe 这显然没有帮助,因为 Project1.exe 使用 ExeName 来确定 exe 所在的目录,以及保存各种共享配置和应用程序特定文件的相关目录。

在启动时使用 GetCurrDir() 而不是 ExeName 是一种可能的解决方法。我已经对此进行了测试,无论程序是否通过调试运行,它似乎都能正常工作。

这样做的原因是套件中有几个动态和静态库以及可执行程序 - Project2、Project3 等。将 .dll 和 .exe 文件编译到一个公共位置允许共享应用程序支持文件的单个位置。

也可以在最终输出目录中设置绝对路径。这样做将导致 ExeName 和 ParamStr(0) 值正确,但是,当其他人将套件加载到他们的计算机上时,他们可能不会将其放在完全相同的路径中。目前,该套件可以放置在任何地方,开发人员无需更改任何路径设置即可构建所有套件。

更新:除了 ExeName 问题之外,调试在此“外部”目录中使用 .dll 的 exe 无法发生,因为在具有错误 ExeName 的调试器下,可执行文件找不到 .dll,尽管它们位于该文件夹中。“运行(不调试)”也无法找到 .dll 文件。从外部 IDE 运行此 .exe 有效。将工作目录设置为目标 .exe 路径(绝对)有效。使用亲戚是行不通的。

最好知道为什么 IDE 会以这种方式运行,以及这是否是可以改进的地方,或者是否有其他方法可以解决这个问题。

C++builder-11-亚历山大

评论

0赞 Remy Lebeau 8/27/2022
TApplication::ExeName只是调用 ,而 又只是调用 ,它报告创建调用进程的模块的完整路径,正如操作系统所知道的那样。因此,路径应始终有效且准确。它是否包含额外的和在里面是另一回事。ParamStr(0)GetModuleFileName(NULL)...
0赞 Mark Di Val 8/27/2022
嗨,雷米 - 一如既往,感谢您的输入。这不是我所看到的。在项目文件目录树之外的“最终输出目录”中设置相对值会导致 ExeName 值,该值是项目文件路径与应用程序报告的相对路径的串联。我想调试器在启动进程时正在设置一个参数。我的测试项目位于 OneDrive 上:1drv.ms/u/s!AjROG9fNzRVXhrwMXGlN4PMW5_g1Vw?e=P9SORt
0赞 Remy Lebeau 8/27/2022
然而,我所描述的是真正发生的事情。看看 RTL 的源代码:...... 根据 MSDN:“如果 [hModule] 为 NULL,则 GetModuleFileName 检索当前进程的可执行文件的路径function TApplication.GetExeName: string; begin Result := ParamStr(0); end;function ParamStr(Index: Integer): string; var ... Buffer: array[0..260] of Char; begin Result := ''; if Index = 0 then SetString(Result, Buffer, GetModuleFileName(0, Buffer, Length(Buffer))) else ... end;"
0赞 Remy Lebeau 8/27/2022
IDE 执行的任何操作都不应影响报告。GetModuleFileName(0)
0赞 Mark Di Val 8/27/2022
我认为调试器(或 IDE)正在将最终输出目录中的任何内容传递给 CreateProcessW() 调用 - 可能是 lpApplicationName 参数,该参数可以是完整路径或部分路径,如文档中所述:“字符串可以指定要执行的模块的完整路径和文件名,也可以指定部分名称。对于部分名称,该函数使用当前驱动器和当前目录来完成规范。该函数将不使用搜索路径。此参数必须包含文件扩展名;不假定默认扩展名。

答: 暂无答案