【问题标题】:What is the default working directory of a Delphi or C++Builder applicationDelphi 或 C++Builder 应用程序的默认工作目录是什么
【发布时间】:2018-02-23 20:21:39
【问题描述】:

我正在维护一些用 Delphi 6 和 C++Builder 4 编写的旧应用程序。使用这两种编译器编译的应用程序会出现一种看起来很奇怪的现象。他们倾向于记住他们的默认工作目录,即使 .exe 被复制到不同的目录。确定默认工作目录的机制是什么,以及如何知道默认工作目录何时不是 .exe 所在的目录?

示例:假设我在C:\CppBuilder\Projects\MyApp 中有源代码和已编译的 32 位 PE MyApp.exe。然后我将MyApp.exe 和该文件夹中的其他文件复制到USB 闪存盘F:\。然后,在资源管理器中,我双击 MyApp.exe 中的 F:\ 并启动应用程序。使用 fopen 打开的文件仍然从 C:\CppBuilder\Projects\Myapp 打开。如果我重命名或删除文件夹C:\CppBuilder\Projects\Myapp,那么输入文件将从F:\ 打开,正如我所期望的那样。文件打开对话框的默认文件夹也类似。

这背后的机制是什么?

对不起,如果这是一个愚蠢的问题,但我真的找不到答案,我不好意思说,它时不时让我发疯。我想确定从哪里打开文件,而不是在文件名中使用完整路径。再次,我很抱歉。如果你知道答案,请帮助我。

【问题讨论】:

  • 他们倾向于记住他们的默认工作目录,即使 .exe 被复制到不同的目录。这是现代操作系统的一个功能
  • 进程的初始工作目录是运行EXE的文件夹,除非EXE是由另一个应用程序启动的,在这种情况下,初始工作目录是父进程的工作目录,除非另有说明(例如,通过CreateProcess()ShellExecute/Ex() 的参数)。 fopen() 不应该发生您所描述的事情(无论如何,您不应该使用相对路径)。
  • 文件对话框,另一方面,是完全不同的东西。他们有自己的规则来确定他们显示的初始目录。调用进程的工作目录只是他们考虑的众多因素之一。文件对话框 API 函数的特定规则记录在 MSDN 中。
  • 如果您使用相对文件名,那么您将得到您想要的。您不控制工作目录。您说您不想使用绝对路径,但这就是问题所在。做正确的想法。使用绝对路径。问题解决了。
  • 我通常在我的应用程序开始时将任何对话框或文件浏览器的目录设置为相对于使用ExtractFilePath(Application->ExeName);获得的exe路径以避免此类问题...`

标签: delphi c++builder


【解决方案1】:

Delphi 和 C++ builder 应用程序的工作目录与大多数其他应用程序相同。 GetCurrentDir 总是返回正确的工作目录,默认为 exe 目录。但是在 VCL 打开/保存对话框中,如果您在使用最后使用的目录时没有指定 InitialDir 属性。

【讨论】:

  • 没有。默认情况下,它是父进程的工作目录。但是当你双击一个exe时,shell会将它设置为exe目录。
  • 当然,默认情况下,我的意思是从用户的角度来看,当您双击文件时(如问题中所述)
【解决方案2】:

这是 Windows 7 及更高版本的一项功能,在对 GetOpenFileName()GetSaveFileName() 的基础调用中。

具体来说,OPENFILENAME 结构的lpstrInitialDir 字段的文档说:

lpstrInitialDir
类型:LPCTSTR

初始目录。选择初始目录的算法因平台而异。

Windows 7:

  1. 如果 lpstrInitialDir 的值与应用程序第一次使用“打开”或“另存为”对话框时传递的值相同,则用户最近选择的路径将用作初始目录。李>
  2. 否则,如果 lpstrFile 包含路径,则该路径是初始目录。
  3. 否则,如果 lpstrInitialDir 不为 NULL,则指定初始目录。
  4. 如果 lpstrInitialDir 为 NULL 且当前目录包含指定过滤器类型的任何文件,则初始目录为当前目录。
  5. 否则初始目录为当前用户的个人文件目录。
  6. 否则初始目录为桌面文件夹。

Windows 2000/XP/Vista:

  1. 如果 lpstrFile 包含路径,则该路径是初始目录。
  2. 否则,lpstrInitialDir 指定初始目录。
  3. 否则,如果应用程序过去使用过“打开”或“另存为”对话框,则选择最近使用的路径作为初始目录。但是,如果应用程序长时间未运行,则其保存的选定路径将被丢弃。
  4. 如果 lpstrInitialDir 为 NULL 且当前目录包含指定过滤器类型的任何文件,则初始目录为当前目录。
  5. 否则初始目录为当前用户的个人文件目录。
  6. 否则初始目录为桌面文件夹。

此外,调用公用文件对话框,除非设置了OFN_NOCHANGEDIR 标志,will continuously change your application's working directory 是在该对话框中选择的最后一个 - 无论文件是否被选择/保存。即使指定了OFN_NOCHANGEDIR,工作目录仍会在用户导航对话框时更改,但在对话框关闭时会恢复。这使得相对路径在多线程上下文中特别不安全。

fopen 将在打开具有相对路径的文件时使用当前工作目录,因此只有当应用程序先前更改其工作目录或通过调用上述通用文件对话框进行更改时,这些调用才会受到影响。

【讨论】:

  • 另请注意,GetOpenFileName()/GetSaveFileName() 在用户从一个文件夹导航到另一个文件夹时会改变调用进程的当前工作目录。如果您没有在OPENFILENAME::Flags 字段中指定OFN_NOCHANGEDIR 标志,则对话框关闭时将不会恢复原来的当前工作目录。
  • 问题说用 fopen 打开的文件
  • @DavidHeffernan fopen 使用当前工作目录 afaik,而改变这一点的是对对话框函数的调用。
  • 当然,如果先打开文件对话框
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-11
  • 2017-10-28
  • 2021-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多