getmodulefilenamew 是 windows 下获取当前进程可执行文件绝对路径最直接可靠的方法,它通过pe模块信息获取路径,不受工作目录、启动方式影响,而 std::filesystem::current_path() 返回的是进程启动时的工作目录,与.exe位置无关。

Windows 下用 GetModuleFileName 获取当前进程路径最直接、最可靠;std::filesystem::current_path() 返回的是工作目录,不是可执行文件路径,别混用。
为什么 std::filesystem::current_path() 不是你要的路径
它返回的是进程启动时所在的工作目录(current working directory),和你的 .exe 文件位置完全无关。比如你在 D:\proj 下双击运行 C:\bin\app.exe,current_path() 返回的是 D:\proj,不是 C:\bin\app.exe。
常见误用场景:
- 想读取同目录下的配置文件
config.json,结果在错误目录下找 - 拼接资源路径时用
current_path() / "data",导致路径错乱
GetModuleFileName 是 Windows 下最稳的选择
它通过 Windows API 直接查 PE 模块加载信息,拿到的是当前进程主模块(即 .exe)的完整绝对路径,不依赖环境变量或工作目录,启动方式(命令行、快捷方式、IDE 调试)都不影响结果。
实操要点:
- 传
NULL作为第一个参数表示当前进程 - 缓冲区大小必须用
MAX_PATH(260)或更大,避免截断(尤其启用长路径支持后) - 返回值是实际写入的字符数,为 0 表示失败,需检查
GetLastError() - 结果是宽字符(
wchar_t),若需std::string,用std::wstring_convert或 C++11 后推荐的WideCharToMultiByte
简例:
wchar_t path[MAX_PATH] = {0};
DWORD len = GetModuleFileNameW(NULL, path, MAX_PATH);
if (len == 0 || len >= MAX_PATH) {
// 错误处理
}
std::wstring exe_path(path); // 完整路径,含文件名
跨平台?别硬套 std::filesystem,Linux/macOS 用 /proc/self/exe 或 _NSGetExecutablePath
C++20 的 std::filesystem::canonical("argv[0]") 理论上可行,但有严重缺陷:如果 argv[0] 是相对路径或被篡改(如 shell 封装脚本),结果不可靠;且 macOS 不支持 canonical 对符号链接的解析。
各平台真实可用方案:
- Windows:坚持用
GetModuleFileNameW - Linux:读取
/proc/self/exe符号链接(readlink) - macOS:调用
_NSGetExecutablePath(需<mach-o></mach-o>),注意缓冲区要足够大并重试
没有一行代码通吃三端。强行封装成统一接口时,内部仍得按平台分叉,别被 filesystem 的名字误导。
真正容易被忽略的是路径结尾是否带反斜杠、是否需要去除文件名——GetModuleFileName 返回的是完整路径(如 C:\app\main.exe),提取目录要用 std::filesystem::path(exe_path).parent_path(),别手撕字符串;另外,某些安全策略或沙盒环境(如 Windows AppContainer)可能限制该 API,返回空或拒绝访问,上线前务必在目标环境中实测。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











