今天,我想幫跟蹤並修復一個非常常見且非常著名的異常:System.IO.FileNotFoundException。承認!在所有情況下,此錯誤都是由於嘗試訪問不存在的文件所致。但是,實際上有多種情況可以觸發此異常。你可能認為你知道關於這個例外的一切,但我打賭你還有一些東西要學。至少我在深入了解這篇文章的細節時做到了。請繼續關注以了解全部情況。
文件類型未找到錯誤
找不到文件“filename”
如消息所述,您正在嘗試加載找不到的文件。可以使用一行代碼復現此類錯誤:
try { File.ReadAllText("non-existing.file"); } catch (FileNotFoundException e) { Console.WriteLine(e.ToString()); }
第三行是這里最重要的一條。我正在嘗試加載文件系統中不存在的文件(non existing.file)。在上面的示例中,程序將輸出打印到控制台,如下所示:
System.IO.FileNotFoundException: Could not find file 'APP_PATH\bin\Debug\non-existing.file'. File name: 'APP_PATH\bin\Debug\non-existing.file' at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost) at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize, Boolean checkHost) at System.IO.File.InternalReadAllText(String path, Encoding encoding, Boolean checkHost) at System.IO.File.ReadAllText(String path) at ConsoleApp.Program.Main(String[] args) in APP_PATH\Program.cs:line 19
APP_PATH將是找不到的文件的絕對路徑。這種類型的FileNotFoundException實際上包含調試問題所需的所有信息。異常消息包含一個很好的錯誤描述,以及丟失文件的絕對路徑。如果要向用戶顯示路徑,或者在找不到文件時創建該文件,則FileNotFoundException上有一個nifty屬性可用:
catch (FileNotFoundException e) { File.Create(e.FileName); }
在本例中,我只是使用Filename屬性創建丟失的文件。我已經看到代碼解析異常消息以獲取丟失文件的名稱,當絕對路徑在異常上可用時,這有點讓人失望。
系統找不到指定的文件。(HRESULT的異常:0x80070002)
此錯誤通常在嘗試加載不存在的程序集時引發。可以這樣復現錯誤:
try { Assembly.LoadFile("c:\\Nonexisting.dll"); } catch (FileNotFoundException e) { Console.WriteLine(e.ToString()); }
在這種情況下,程序仍然拋出一個FileNotFoundException。但異常消息不同:
System.IO.FileNotFoundException: The system cannot find the file specified. (Exception from HRESULT: 0x80070002) at System.Reflection.RuntimeAssembly.nLoadFile(String path, Evidence evidence) at System.Reflection.Assembly.LoadFile(String path) at ConsoleApp.Program.Main(String[] args) in APP_PATH\Program.cs:line 20
與讀取丟失文件時引發的錯誤不同,來自System.Reflection命名空間的消息更難理解。若要查找此錯誤的原因,您需要查看堆棧跟蹤,該跟蹤提示這是在Assembly.LoadFile期間發生的。注意,異常消息中不存在文件名,在本例中,FileNotFoundException上的filename屬性為空。
無法加載文件或程序集“assembly”或其依賴項之一。系統找不到指定的文件。
與上述錯誤類似的錯誤是無法加載文件或程序集“assembly”或其依賴項之一。系統找不到指定的文件。錯誤。這也意味着程序正在嘗試加載找不到的程序集。可以通過創建使用其他程序集的程序來重新創建錯誤。生成程序,從bin\Debug文件夾中刪除引用程序集(.dll文件),然后運行程序。在這種情況下,程序在啟動時失敗:
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'Lib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified. at ConsoleApp.Program.Main(String[] args)
在本例中,我引用了一個名為Lib的程序集,它不存在於磁盤或全局程序集緩存(GAC)中。此錯誤的典型原因是引用的程序集不在文件系統上。這可能有多種原因。為了幫助您調試,需要檢查以下幾點:
- 如果要使用Azure DevOps或Octopus Deploy等系統進行部署,請確保將生成輸出中的所有文件復制到目標。
- 在Visual Studio中的引用程序集上單擊鼠標右鍵,單擊“屬性”,並確保“復制本地”設置為true:
在IIS上運行時出現訪問錯誤
要確保應用程序池用戶具有訪問權限,請執行以下操作:
- 右鍵單擊包含web應用程序的文件夾
- 單擊屬性
- 選擇“安全”選項卡
- 單擊編輯。。。
- 單擊添加。。。
- 在文本區域中輸入IIS AppPool\DefaultAppPool
- 單擊“檢查名稱”並驗證是否已解析用戶
- 單擊“確定”
- 將完全控制權分配給新用戶並保存