首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

C++ 獲取當前路徑完全指南:GetCurrentDirectory vs GetModuleFileName、Unicode 支持與調試陷阱

     編輯:C++ 入門

兩大核心需求區分

需求API含義調試陷阱
進程工作目錄GetCurrentDirectory進程啟動/運行時的「當前目錄」 (可被 chdir/SetCurrentDirectory 改變)VS 調試時工作目錄 = 項目目錄,非 Debug/Release 輸出目錄!
模塊(EXE/DLL)所在目錄GetModuleFileName可執行文件/加載模塊的完整路徑,提取目錄部分動態加載 DLL 時獲取的是 DLL 路徑,需傳 NULL 獲取 EXE 路徑

方案一:獲取工作目錄 (C 風格 / MFC)


// C 風格 (需 )
#include 
#include 

std::string GetWorkingDir() {
    char buffer[MAX_PATH];
    DWORD len = GetCurrentDirectoryA(MAX_PATH, buffer);
    if (len == 0 || len > MAX_PATH) return "";
    return std::string(buffer, len);
}

// MFC CString 版
CString GetWorkingDirMFC() {
    CString path;
    GetCurrentDirectory(MAX_PATH, path.GetBuffer(MAX_PATH));
    path.ReleaseBuffer();
    return path;
}

方案二:獲取 EXE 所在目錄 (健壯、推薦)


// 通用版 (支持 Unicode TCHAR)
#include 
#include 
#include 
#include  // PathRemoveFileSpec
#pragma comment(lib, "shlwapi.lib")

std::wstring GetExeDir() {
    wchar_t path[MAX_PATH];
    // NULL 代表當前進程 EXE
    DWORD len = GetModuleFileNameW(nullptr, path, MAX_PATH);
    if (len == 0 || len == MAX_PATH) return L""; // 截斷需動態分配
    
    PathRemoveFileSpecW(path); // 就地移除文件名,保留目錄 (含尾部反斜槓)
    return std::wstring(path);
}

// 無 Shlwapi 手動版
std::wstring GetExeDirManual() {
    wchar_t path[MAX_PATH];
    GetModuleFileNameW(nullptr, path, MAX_PATH);
    std::wstring ws(path);
    size_t pos = ws.find_last_of(L"\\/");
    if (pos != std::wstring::npos) ws.resize(pos + 1); // 保留分隔符
    return ws;
}

關鍵技術細節

  1. Unicode 統一用 W 版 API:GetModuleFileNameW、wchar_t、std::wstring,避免 ANSI 代碼頁亂碼。
  2. MAX_PATH 限制 (260):長路徑可能截斷。現代 Windows 10+ (版本 1607+) 支持長路徑,需清單啟用或用 \\?\ 前綴。安全做法:動態分配緩衝區 (std::vector 循環增大調用)。
  3. PathRemoveFileSpec 就地修改:高效移除文件名,保留目錄分隔符。
  4. DLL 中獲取 EXE 路徑:GetModuleFileNameW(nullptr, ...)。若需 DLL 自身路徑,傳 GetModuleHandleW(L"mydll.dll") 或 &__ImageBase (MSVC 特有)。

現代 C++17 跨平台方案:std::filesystem


#include 
#include 

namespace fs = std::filesystem;

int main() {
    // 1. 當前工作目錄 (跨平台)
    fs::path cwd = fs::current_path(); 
    std::cout << "CWD: " << cwd << std::endl;
    
    // 2. 可執行文件路徑 (C++20: std::filesystem::executable_path() / C++17 需平台特定)
    // Windows:
    wchar_t buf[MAX_PATH];
    GetModuleFileNameW(nullptr, buf, MAX_PATH);
    fs::path exePath = buf;
    std::cout << "EXE Dir: " << exePath.parent_path() << std::endl;
    
    // 3. 路徑操作 (拼接、刪除文件名、擴展名、規範化)
    fs::path logDir = exePath.parent_path() / "logs";
    fs::create_directories(logDir); // 遞歸創建
    
    return 0;
}

總結建議

  1. 配置文件/數據文件讀寫:用 **EXE 所在目錄** (GetModuleFileName / fs::executable_path),穩定不受工作目錄變更影響。
  2. 相對路徑處理/用戶交互:用 **工作目錄** (GetCurrentDirectory / fs::current_path)。
  3. 新項目強制用 std::filesystem:跨平台、類型安全、路徑運算符重載、UTF-8/UTF-16 自動處理。
  4. 調試時設置工作目錄:VS 項目屬性 → 調試 → 工作目錄 設為 $(OutDir) 或數據目錄,使調試行為與發布一致。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved