【发布时间】:2011-02-08 11:58:16
【问题描述】:
我需要在 Windows 上的 C++ 应用程序中使用 fstream 访问一些文件。这些文件都位于我的exe文件所在文件夹的子文件夹中。
- 什么是最简单和更重要的:获取当前可执行文件文件夹路径的最安全方法?
【问题讨论】:
-
比使用 argv[0] 作为 int main (int argc, char *argv[]) 的参数并对其进行解析更复杂的方法?
我需要在 Windows 上的 C++ 应用程序中使用 fstream 访问一些文件。这些文件都位于我的exe文件所在文件夹的子文件夹中。
【问题讨论】:
使用GetModuleFileName 找出您的 exe 是从哪里运行的。
WCHAR path[MAX_PATH];
GetModuleFileNameW(NULL, path, MAX_PATH);
然后从路径中去除 exe 名称。
【讨论】:
GetModuleFileNameW(NULL, path, MAX_PATH) 还不够吗?
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);
【讨论】:
PathRemoveFileSpec,不知道。
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"
默认情况下,运行 exe 的目录应该是起始位置。所以在子文件夹中打开文件应该像
一样简单fstream infile;
infile.open(".\\subfolder\\filename.ext");
在您的程序中。
但是,没有真正的方法可以保证这将始终有效,除非您使用包含所需功能的框架(我会查看 boost),或者直接使用 Windows API,例如 GetModuleFileName(作为 sean e 建议)
【讨论】:
GetCurrentDirectory() 的API 调用检查此目录,或使用SetCurrentDirectory() 设置它。虽然我意识到这不是您问题的确切解决方案(正如我在原文中所述),但信息并没有错msdn.microsoft.com/en-us/library/aa363806.aspx。如果您认为值得一票否决,我不确定您是否了解此处投票系统的预期用途。
cmd启动程序时,当前工作目录将从父进程继承。您真的不能假设 CWD 与可执行映像的位置有任何关系。