2016/05/24

IOUtils TDirectory.CreateDirectory 跳出 The drive cannot be found 錯誤

最近使用 IOUtils 單元的 TDirectory.CreateDirectory 來處理目錄建立的工作。

MSDN中說明這個函式的功能:
按照 path 所指定的來建立所有目錄和子目錄。

備註
會建立 path 中指定的任何和所有目錄,除非它們已經存在,或 path 的某些部分是無效的。path 參數指定的是目錄路徑,而不是檔案路徑。如果目錄已經存在,這個方法不執行任何動作。
所以DirectoryExists這類的工作都可以拿掉了,是個很方便的功能。

程式運作了好一陣子,都沒有出問題,一直到某天,客戶回傳了一個錯誤視窗:


於是,我又踏上抓鬼之路了。
  接著我請了個道士來 Debug   圖片來源


雖然已知是「TDirectory.CreateDirectory」造成的錯誤,但為什麼客戶會出現但我這裡完全沒事呢?


後來才知道,原來客戶的環境是以虛擬機器運作,以 UNC 路徑執行所有程式,看來就是 UNC 路徑搞的鬼。

What is "UNC"?就是像「\\ComputerName\DirectoryName」這樣的網路路徑。

總之,Bug找到了!讓我們來看看「它」長什麼樣子吧!



Bug 示意圖.........  圖片來源
































咳!………還是回到正題!


仔細研究原始碼,才發現在 IOUtils.pas 單元的函式出錯:
class procedure TDirectory.CheckCreateDirectoryParameters(const Path: string);

出錯的程式碼為:
if not TPath.DriveExists(TPath.DoGetPathRoot(Path)) then

因為沒有針對 UNC 路徑多做判斷,所以一定會跑「The drive cannot be found」錯誤。

找到了Bug,但要如何解決呢?很簡單,將出錯的那一列置換如下:
if TPath.IsDriveRooted(Path) and not TPath.DriveExists(TPath.DoGetPathRoot(Path)) then


如此便修正了這個問題,但最好是將底下路徑的IOUtils.dcu一併置換:
$(BDS)\lib\win32\debug
$(BDS)\lib\win32\release
$(BDS)\source\rtl\common


或是把 IOUtils.pas 複製到自己的專案進行修改後使用。


















最後,這個Bug在XE3之後已被修正。

See also:

沒有留言:

張貼留言