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

CFile::Open 預設路徑陷阱:CFileDialog 會改變進程工作目錄

     編輯:關於VC++

在 MFC 開發中,CFile::Open 若未指定完整路徑,預設會在進程目前工作目錄尋找檔案。然而,一旦呼叫過 CFileDialog 並由使用者選取檔案,進程的工作目錄就會被切換至該檔案所在資料夾,導致後續相對路徑開啟檔案行為改變。本文說明此現象並提供因應對策。

現象重現

  1. 程式啟動未開啟任何檔案對話框 → GetCurrentDirectory 回傳專案執行檔目錄(如 D:\MyApp\)。
  2. 呼叫 CFileDialog 選取 C:\Program Files\desktop.ini → 關閉對話框後,GetCurrentDirectory 變為 C:\Program Files\。
  3. 此時若以相對路徑 CFile::Open("data.dat"),實際會去 C:\Program Files\data.dat 而非專案目錄。

程式碼驗證片段

CString strPath;
GetCurrentDirectory(MAX_PATH, strPath.GetBuffer(MAX_PATH));
strPath.ReleaseBuffer();
AfxMessageBox(_T("目前工作目錄:\n") + strPath);

根本原因

CFileDialog 內部呼叫 GetOpenFileName,該 API 預設會將進程工作目錄設為使用者最後瀏覽的資料夾(除非指定 OFN_NOCHANGEDIR 標旗,但 MFC 封裝未暴露此選項)。

解決方案

方案 A:儲存初始目錄(推薦)

// 專案啟動時
CString g_strAppPath;
GetCurrentDirectory(MAX_PATH, g_strAppPath.GetBuffer(MAX_PATH));
g_strAppPath.ReleaseBuffer();

// 後續開檔
CFile file;
file.Open(g_strAppPath + _T("\\data.dat"), CFile::modeRead);

方案 B:永遠使用完整路徑

配合 CFileDialog::GetPathName() 取得完整路徑傳給 CFile::Open,避免相對路徑歧義。

方案 C:手動還原目錄

CFileDialog 關閉後呼叫 SetCurrentDirectory(g_strAppPath),但不建議,因多執行緒環境下會互相干擾。

最佳實務建議

  • 程式啟動即記錄應用程式目錄,全程使用絕對路徑。
  • 避免依賴進程工作目錄,因任何 Shell 對話框、第三方 DLL 皆可能竄改它。
  • 若必須使用相對路徑,請在呼叫前後用 Get/SetCurrentDirectory 成對保護(需考慮執行緒安全)。

這是 MFC 開發中常見卻易被忽略的坑,理解機制後即可輕鬆規避。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved