【问题标题】:C++ [Windows] Path to the folder where the executable is located [duplicate]C ++ [Windows]可执行文件所在文件夹的路径[重复]
【发布时间】:2011-02-08 11:58:16
【问题描述】:

我需要在 Windows 上的 C++ 应用程序中使用 fstream 访问一些文件。这些文件都位于我的exe文件所在文件夹的子文件夹中。

  • 什么是最简单和更重要的:获取当前可执行文件文件夹路径的最安全方法?

【问题讨论】:

  • 比使用 argv[0] 作为 int main (int argc, char *argv[]) 的参数并对其进行解析更复杂的方法?

标签: c++ windows


【解决方案1】:

使用GetModuleFileName 找出您的 exe 是从哪里运行的。

WCHAR path[MAX_PATH];
GetModuleFileNameW(NULL, path, MAX_PATH);

然后从路径中去除 exe 名称。

【讨论】:

  • 没有 Win32 API 有没有办法做到这一点?
  • @asas:不,这不是一种简单安全的方法。
  • @asas:在不使用 Win32 API 的情况下编写 C++ Windows 应用程序?喜欢改用 Qt 吗?
  • sean e:是的,没有 Win32 API。它不是 GUI 应用程序 - 它是我目前在 MSVC 中编写的解释器,移植起来应该不会太难 - Win32 API 很难移植。
  • 我知道这真的很老了,但GetModuleFileNameW(NULL, path, MAX_PATH) 还不够吗?
【解决方案2】:

GetThisPath.h

/// dest is expected to be MAX_PATH in length.
/// returns dest
///     TCHAR dest[MAX_PATH];
///     GetThisPath(dest, MAX_PATH);
TCHAR* GetThisPath(TCHAR* dest, size_t destSize);

GetThisPath.cpp

#include <Shlwapi.h>
#pragma comment(lib, "shlwapi.lib")

TCHAR* GetThisPath(TCHAR* dest, size_t destSize)
{
    if (!dest) return NULL;
    if (MAX_PATH > destSize) return NULL;

    DWORD length = GetModuleFileName( NULL, dest, destSize );
    PathRemoveFileSpec(dest);
    return dest;
}

mainProgram.cpp

TCHAR dest[MAX_PATH];
GetThisPath(dest, MAX_PATH);

更新:PathRemoveFileSpec 在 Windows 8 中已弃用。但是,替代品 PathCchRemoveFileSpec 仅在 Windows 8+ 中可用。 (感谢@askalee 的评论)

我认为下面的代码可能有效,但我将上面的代码保留在那里,直到下面的代码被审查。我目前没有设置编译器来测试它。如果您有机会测试此代码,请发表评论说明以下代码是否有效以及您测试的操作系统。谢谢!

GetThisPath.h

/// dest is expected to be MAX_PATH in length.
/// returns dest
///     TCHAR dest[MAX_PATH];
///     GetThisPath(dest, MAX_PATH);
TCHAR* GetThisPath(TCHAR* dest, size_t destSize);

GetThisPath.cpp

#include <Shlwapi.h>
#pragma comment(lib, "shlwapi.lib")

TCHAR* GetThisPath(TCHAR* dest, size_t destSize)
{
    if (!dest) return NULL;

    DWORD length = GetModuleFileName( NULL, dest, destSize );
#if (NTDDI_VERSION >= NTDDI_WIN8)
    PathCchRemoveFileSpec(dest, destSize);
#else
    if (MAX_PATH > destSize) return NULL;
    PathRemoveFileSpec(dest);
#endif
    return dest;
}

mainProgram.cpp

TCHAR dest[MAX_PATH];
GetThisPath(dest, MAX_PATH);

【讨论】:

  • +1 PathRemoveFileSpec,不知道。
  • 似乎不推荐使用 PathRemoveFileSpec:msdn.microsoft.com/en-us/library/windows/desktop/…,请改用 PathCchRemoveFileSpec。
  • @askalee 值得一提的是,它仅受 Win8(及更高版本)桌面应用程序支持
  • 当我意识到这在 Windows 8 上不起作用时,我正准备实施它。例如Windows 8.1 是 NTDDI_WINBLUE,而不是 NTDDI_WIN8。你会想要类似`#if (NTDDI_VERSION >= NTDDI_WIN8)`的东西`
  • PathCchRemoveFileSpec 不工作,我从 #pragma comment(lib, "Pathcch.lib") 打来电话,但我收到错误 argument type "TCHAR *" is incompatible with the parameter type "PWSTR"
【解决方案3】:

默认情况下,运行 exe 的目录应该是起始位置。所以在子文件夹中打开文件应该像

一样简单
fstream infile; 
infile.open(".\\subfolder\\filename.ext");

在您的程序中。

但是,没有真正的方法可以保证这将始终有效,除非您使用包含所需功能的框架(我会查看 boost),或者直接使用 Windows API,例如 GetModuleFileName(作为 sean e 建议)

【讨论】:

  • 什么?你听说过run in吗?你不用告诉我exe运行的路径是默认的……
  • 如果您误解:每个进程都有自己的值来表示当前目录。默认情况下,该值应设置为可执行文件所在的目录。您可以使用GetCurrentDirectory() 的API 调用检查此目录,或使用SetCurrentDirectory() 设置它。虽然我意识到这不是您问题的确切解决方案(正如我在原文中所述),但信息并没有错msdn.microsoft.com/en-us/library/aa363806.aspx。如果您认为值得一票否决,我不确定您是否了解此处投票系统的预期用途。
  • 他可能指的是“开始”选项,您可以在其中指定 Windows 开始菜单程序链接中的起始工作目录。
  • 答案不完整,但我认为它不值得投反对票。
  • 除了具有明确指定工作目录的快捷方式外,例如从cmd启动程序时,当前工作目录将从父进程继承。您真的不能假设 CWD 与可执行映像的位置有任何关系。
猜你喜欢
  • 1970-01-01
  • 2020-12-11
  • 2017-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-24
相关资源
最近更新 更多