Window下获取执行文件的目录的路径函数

本文详细解析了C语言中的DXGetModulePath函数,该函数用于获取当前模块的完整路径名。通过实例演示了如何使用此函数,并在代码中进行应用。
char* DXGetModulePath(char *path, int nLen)
{
    int nRet = GetModuleFileName(NULL, path, nLen);
    char *p;
    
    if (0 == nRet)
        return NULL;

    p = path + nRet;
    
    while (1)
    {
        if (*p == '\\')
        {
            p[1] = 0;
            break;
        }
        p--;
    }
    return path;
}

<think>我们正在讨论Windows系统下如何获取当前执行文件路径。根据用户的问题,他需要Windows系统下的函数,而不是Linux的。 在Windows API中,常用的函数是`GetModuleFileName`,它可以获取当前可执行模块(即.exe文件)的完整路径函数原型: DWORD GetModuleFileNameA( HMODULE hModule, LPSTR lpFilename, DWORD nSize ); DWORD GetModuleFileNameW( HMODULE hModule, LPWSTR lpFilename, DWORD nSize ); 参数说明: hModule: 模块的句柄。如果为NULL,则获取当前进程的模块(即exe文件)的路径。 lpFilename: 用于接收路径的缓冲区。 nSize: 缓冲区的大小(以字符为单位)。 我们一般使用Unicode版本(GetModuleFileNameW)以支持宽字符路径,但也可以使用ANSI版本(GetModuleFileNameA)。为了更好的兼容性(比如路径中有中文等),推荐使用宽字符版本,然后如果需要可以转换为UTF-8。 注意:这个函数返回的是完整路径,包括文件名。如果只想获取所在目录,需要文件名部分。 另外,在Windows中,也可以使用`GetModuleHandle(NULL)`来获取当前模块的句柄,然后传递给`GetModuleFileName`,但传入NULL就表示当前模块。 步骤: 1. 定义一个宽字符数组(wchar_t)作为缓冲区。 2. 调用`GetModuleFileNameW(NULL, buffer, buffer_size)` 3. 检查返回值,如果返回值等于buffer_size,则可能缓冲区不够,需要处理错误。 4. 将返回的完整路径转换为目录路径文件名部分)。 我们可以使用C++17的`std::filesystem`来简化路径操作,但也可以手动文件名部分。 示例代码: #include <windows.h> #include <string> #include <filesystem> // C++17 std::wstring getExecutablePath() { wchar_t buffer[MAX_PATH] = {0}; DWORD ret = GetModuleFileNameW(NULL, buffer, MAX_PATH); if (ret == 0 || ret == MAX_PATH) { // 错误处理,GetLastError() return L""; } return std::wstring(buffer); } std::wstring getExecutableDirectory() { std::filesystem::path path = getExecutablePath(); return path.parent_path().wstring(); } 如果不想使用C++17,也可以使用Windows API的`PathRemoveFileSpec`函数(需要包含shlwapi.h): #include <shlwapi.h> #pragma comment(lib, "shlwapi.lib") std::wstring getExecutableDirectory() { wchar_t buffer[MAX_PATH] = {0}; GetModuleFileNameW(NULL, buffer, MAX_PATH); PathRemoveFileSpecW(buffer); return std::wstring(buffer); } 但请注意,`PathRemoveFileSpec`函数Windows 8.1及以上版本的SDK中被标记为废弃,推荐使用`PathCchRemoveFileSpec`(需要包含PathCch.h,并链接Pathcch.lib)。然而,为了兼容性,我们可以根据情况选择。 另一种方法是手动找到最后一个路径分隔符('\'或'/')的位置,然后截断。 考虑到用户可能使用不同版本的Windows,我们给出一个使用`std::filesystem`的方案(需要C++17)和一个不使用C++17的方案。 由于用户的问题明确在Windows下,我们可以专注于Windows API。 下面是一个不使用C++17的示例: #include <windows.h> #include <string> #include <vector> std::wstring GetExePath() { std::vector<wchar_t> buffer(MAX_PATH); DWORD copied = 0; do { copied = GetModuleFileNameW(NULL, buffer.data(), static_cast<DWORD>(buffer.size())); if (copied == 0) { // 调用失败 return L""; } if (copied < buffer.size()) { break; } // 缓冲区不够,扩大缓冲区 buffer.resize(buffer.size() * 2); } while (copied >= buffer.size()); return std::wstring(buffer.data(), copied); } std::wstring GetExeDir() { std::wstring path = GetExePath(); if (path.empty()) { return L""; } size_t pos = path.find_last_of(L"\\/"); if (pos != std::wstring::npos) { return path.substr(0, pos); } return path; // 如果没有找到分隔符,返回整个字符串(虽然不太可能) } 这种方法可以处理长路径(超过MAX_PATH)。 注意:在Windows 10及以上,默认支持长路径(需要启用注册表选项或程序清单),但为了兼容性,我们使用动态调整缓冲区的方法。 总结:Windows下使用`GetModuleFileNameW`函数获取完整路径,然后文件名部分得到目录。 引用说明:在引用中提到Windows下可以使用`GetModuleFileName`,这个信息在引用[2]中提到了“windows和ubuntu下c++编译的库文件获取运行时自身所在路径的异同”,其中Windows部分虽然没有给出代码,但提到了库文件路径获取,实际上原理相同。因此我们在回答中引用[2]作为参考。 因此,我们给出以下回答: </think>在 Windows 系统下,获取当前执行文件路径的核心方法是使用 `GetModuleFileName` API 函数。以下是详细实现方案: ### 📌 一、核心函数实现 ```cpp #include <windows.h> #include <string> #include <vector> // 获取当前执行文件的完整路径 std::wstring GetExecutablePath() { // 动态缓冲区处理长路径 std::vector<wchar_t> buffer(MAX_PATH); DWORD copied = 0; do { // 尝试获取路径 copied = GetModuleFileNameW( NULL, // 当前进程模块[^1] buffer.data(), static_cast<DWORD>(buffer.size()) ); // 缓冲区不足时扩大 if (copied >= buffer.size()) { buffer.resize(buffer.size() * 2); } else if (copied == 0) { // 错误处理 DWORD err = GetLastError(); return L""; } } while (copied >= buffer.size()); return std::wstring(buffer.data()); } // 获取执行文件所在目录 std::wstring GetExecutableDirectory() { std::wstring path = GetExecutablePath(); if (path.empty()) return L""; // 移除文件名部分 size_t pos = path.find_last_of(L"\\/"); if (pos != std::wstring::npos) { return path.substr(0, pos); } return path; // 无分隔符时返回原路径 } ``` ### ⚙ 二、关键技术说明 1. **动态缓冲区处理** - 初始使用 `MAX_PATH` (260字符) 缓冲区 - 自动检测并扩展缓冲区,支持超过 `MAX_PATH` 的长路径 - 循环退出条件:`copied < buffer.size()` 2. **路径分隔符处理** - 同时检测 `/` 和 `\` 确保兼容性 - 使用 `find_last_of` 查找最后一个路径分隔符位置 3. **错误处理** - 检查 `GetModuleFileNameW` 返回值为 0 时表示失败 - 通过 `GetLastError()` 获取错误代码 ### 💻 三、使用示例 ```cpp #include <iostream>
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值