VC++ 取得路徑看似簡單,實則暗藏多處陷阱:GetCurrentDirectory 受檔案對話框影響、GetModuleFileName 需手動截取目錄、PathStripPath 行為不一致。本文系統整理三大場景最佳實務。
char path[MAX_PATH]; GetCurrentDirectory(MAX_PATH, path); // 輸出: "D:\Test"
陷阱:呼叫 CFileDialog、CFile::Open 後,若未設 OFN_NOCHANGEDIR,工作目錄會切換至使用者選擇的資料夾。
對策:
CFileDialog dlg(..., OFN_NOCHANGEDIR | ...);GetCurrentDirectory 存檔,事後 SetCurrentDirectory 還原。CString path;
GetModuleFileName(NULL, path.GetBuffer(MAX_PATH), MAX_PATH);
path.ReleaseBuffer();
int pos = path.ReverseFind('\\');
path = path.Left(pos); // "D:\Test"
CFileDialog dlg(TRUE, NULL, NULL,
OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR,
_T("Text Files (*.txt)|*.txt|All Files (*.*)|*.*||"));
if (dlg.DoModal() == IDOK) {
CString fullPath = dlg.GetPathName(); // 含檔名完整路徑
}
#include#pragma comment(lib, "shlwapi.lib") TCHAR szPath[] = _T("D:\\Test\\tst.exe"); PathStripPath(szPath); // → "tst.exe" TCHAR szDir[] = _T("D:\\Test\\Debug"); PathStripPath(szDir); // → "Debug" (非檔名!)
缺點:無法辨識目錄尾斜線、根目錄會回傳 D:\,非純檔名提取。
CString fullPath;
GetModuleFileName(NULL, fullPath.GetBuffer(MAX_PATH), MAX_PATH);
fullPath.ReleaseBuffer(); // 必須呼叫,否則 GetLength()=0
int pos = fullPath.ReverseFind('\\');
CString exeName = fullPath.Right(fullPath.GetLength() - pos - 1);
| 需求 | 推薦 API | 關鍵點 |
|---|---|---|
| 工作目錄 | GetModuleFileName + 截取 | 不受對話框干擾 |
| 模組完整路徑 | GetModuleFileName | 直接可用 |
| 使用者選檔路徑 | CFileDialog::GetPathName | 加 OFN_NOCHANGEDIR |
| 單純檔名 | 手動 ReverseFind('\\') | 避免 PathStripPath 邊界怪異 |