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

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

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

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

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/5bb295ef072d2a5a2bf8-SNAGHTML152f81fa.png)

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

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/395ae659a08f900c1d02-SNAGHTML15342885.png)

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

但是我們這個專案用 TFS 也一段時間了，直到最近才發生問題才有鬼了，原來是我們要用 [File.Open](http://msdn.microsoft.com/zh-tw/library/system.io.file.open.aspx) 開啟的檔案放在 App\_Data 裡，而這些檔案是寄送電子郵件的郵件內容範本(Template)，而在開發環境時寄信功能是關閉的，所以一直沒有人發現有此問題，直到最近開發環境的郵件功能被打開了（而且程式也簽入 TFS 版本庫），因此只要執行到寄信的功能就會在開啟這些檔案時掛掉！

**最後的結論是**：TFS 版本控管時會將檔案設為唯讀，在使用 .NET 的 File.Open 開啟檔案時會發生 [UnauthorizedAccessException](http://msdn.microsoft.com/zh-tw/library/system.unauthorizedaccessexception.aspx) 例外，所以在開發環境使用時必須將檔案簽出（讓檔案變成可讀寫），或是**修改程式讓你的 .NET 程式可以讀取唯讀檔案的資料** (**建議作法**)。

不過這樣一個簡單的結論卻是經過一段辛苦的追查得知的，當然，如果你今天要開啟檔案時真的只需要讀取資料而已的話，可以用 [File.Open 方法 (String, FileMode, FileAccess)](http://msdn.microsoft.com/zh-tw/library/s67691sb.aspx) 來完成，並指派適當的 [FileAccess](http://msdn.microsoft.com/zh-tw/library/4z36sx0f\(v=vs.80\).aspx) 值，如下範例：

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

**相關連結**

-   [File.Open 方法](http://msdn.microsoft.com/zh-tw/library/system.io.file.open.aspx)

-   [File.Open 方法 (String, FileMode)](http://msdn.microsoft.com/zh-tw/library/b9skfh7s.aspx)
-   [File.Open 方法 (String, FileMode, FileAccess)](http://msdn.microsoft.com/zh-tw/library/s67691sb.aspx)
