The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

TFS 版本控管時會將檔案設為唯讀,需注意 File.Open 的使用

這是上週遇到的問題,我們有個專案參與開發的人比較多,一直以來都用 TFS 進行版本控管與專案管理,一直以來專案在本機開發環境執行的時候都沒遇到過任何問題,但突然有一天所有團隊成員都發生無法讀取特定檔案的問題 ( Access to the path 'C:\Inetpub\wwwroot\App_Data\TEST.txt' is denied ),查到了程式碼發現是在呼叫 File.Open 時發生的錯誤,但檔案權限明明就沒有問題啊!問題要如何解決,請繼續看下去…

由於錯誤訊息是【Access to the path 'C:\Inetpub\wwwroot\App_Data\TEST.txt' is denied.】,當我得知這個問題後也是先往「安全性」的角度出發進行查看,但即便該檔案都設定 Everyone 完全控制了,還是引發例外,因此必須往其他角度��考。

接著我進一步透過 Process Monitor 察看我的程式到底在開啟這個檔案時到底有哪些資訊可查,結果發現也看不出有什麼異狀,基本上我們的程式單純的只是把檔案開啟讀取內容關閉檔案這樣子而已,不知為何有那麼多問題,而詭異的是當下一群人都不知道為什麼程式好好的跑了半年,卻突然有一天所有人的開發環境都掛了,只有部署上架的程式沒問題而已。

解決問題需要創意與跳躍式思考,我後來看見該檔案有個異常的狀況,那就是檔案屬性是「唯讀」的!

當我把檔案的唯讀屬性取消掉之後,所有問題自然迎刃而解,最後才去找出證明這個問題發生的主因,我第一個想到的是從 MSDN 的文件著手,發現 File.Open 方法 有三個多載,一般來說我們為了方便都會用第一個 File.Open 方法 (String, FileMode),不過使用這個方法時當開啟的檔案是唯讀的時候就會引發 UnauthorizedAccessException 例外,這可是天大的發現,因為我們前幾年都是用 Subversion 當作版本控管工具,並沒有唯讀檔案的問題,所以也一直不知道 TFS 會有這個問題。

但是我們這個專案用 TFS 也一段時間了,直到最近才發生問題才有鬼了,原來是我們要用 File.Open 開啟的檔案放在 App_Data 裡,而這些檔案是寄送電子郵件的郵件內容範本(Template),而在開發環境時寄信功能是關閉的,所以一直沒有人發現有此問題,直到最近開發環境的郵件功能被打開了(而且程式也簽入 TFS 版本庫),因此只要執行到寄信的功能就會在開啟這些檔案時掛掉!

最後的結論是TFS 版本控管時會將檔案設為唯讀,在使用 .NET 的 File.Open 開啟檔案時會發生 UnauthorizedAccessException 例外,所以在開發環境使用時必須將檔案簽出(讓檔案變成可讀寫),或是修改程式讓你的 .NET 程式可以讀取唯讀檔案的資料 (建議作法)。

不過這樣一個簡單的結論卻是經過一段辛苦的追查得知的,當然,如果你今天要開啟檔案時真的只需要讀取資料而已的話,可以用 File.Open 方法 (String, FileMode, FileAccess) 來完成,並指派適當的 FileAccess 值,如下範例:

using (FileStream fs = File.Open(filePath, FileMode.Open, FileAccess.Read)) 
{

}

相關連結