同事報案,在ASP.NET 存取 SQLite 資料庫,路徑誤用 ".\Blah.sqlite" (一般多使用 Server.MapPath("~\App_Data\Blah.sqlite"),參考:App_Data的隱身特性 ),程式可以運作,以為 Blah.sqlite 檔案會出現在 bin 目錄但沒有,使用 Everything 搜尋也找不到蹤跡。
這裡有個迷思,依直覺 ASP.NET 伺服器端程式編譯成的 DLL 以及參照的程式庫 DLL 都是放在 bin 目錄,感覺 ASP.NET 的根目錄(或者說工作目錄,".\")應該也在 bin。但事實上,ASP.NET 網站編譯成的組件以 DLL 形式存在,需依附宿主程序(Hosting Process)才能執行,使用 Visual Studio 執行時預設為 C:\Program Files (x86)\IIS Express\iisexpress.exe,若掛在 IIS 則是 C:\Windows\System32\Inetsrv\w3wp.exe。
同事的案例是 VS 偵錯時發現問題,最後在 C:\Program Files (x86)\IIS Express 資料夾找到 Blah.sqlite;若是使用 IIS,理應寫入 C:\Windows\System32\Inetsrv,但 IIS 不像 IIS Express 用當時登入的 Windows 帳號執行,而是限極小的 AppPool 專屬帳號,幾乎都會權限被拒出錯,更容易發現問題。
最後調查本案的另一疑點:為何 Everything 沒有找到 Blah.sqlite?同事回想,是前些時候為了測試增加 exclude 條件導致系統檔案路徑被排除,陰錯陽差之下增添了懸疑性。
全案偵結。
補充小常識:DLL 需依附其他程序執行,故工作目錄預設以程序 EXE 所在位置為準。如果是 Console Application EXE,"." 目錄總會是 EXE 所在資料夾了吧? 倒也不一定,還是有例外。如求萬無一失,可以在程式中執行 Directory.SetCurrentDirectory(Path.GetDirectoryName( Assembly.GetExecutingAssembly().Location)); 以求保險。