The Will Will Web

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

怪問題:當該檔案已經存在時,無法建立或陰影複製

我們有個網站專案,上週在客戶端開發程式時,由於不斷在更新程式,網頁上會不定時出現「當該檔案已經存在時,無法建立或陰影複製」的錯誤訊息,當下看到這個錯誤訊息感覺非常的陌生,我更新網頁程式跟「陰影複製」有何關係?由於該錯誤只要將 IIS 重啟或將應用程式集區回收即可解決,因此沒多留意,也沒將畫面複製下來,但我有用這個技巧將錯誤訊息轉換成英文,好讓下次出現時可進一步分析發生原因。

果不其然,問題又再度發生,這次我就有將畫面複製下來了,如下圖所示,標紅框的地方是組件名稱,且每次出現錯誤的組件都不太一樣。

Cannot create/shadow copy 'xVal' when that file already exists.

從網路上查到大部分資訊都是在開發時期所遇到的問題,但我這次是在客戶端的「模擬正式環境」遇到的,所以感覺很怪,因為怕他下次又再度發作,所以再努力搜尋資料查明原因,找了無數資料後終於瞭解原理。

原來 .NET Framework 有個 陰影複製(Shadow Copy) 機制,且早在 .NET 1.1 就有此機制,從網路搜查到的資料研判應該是在 ASP.NET 2.0 之後該機制預設是啟用的,可能是為了支援 ASP.NET 2.0 動態編譯架構的關係。

當你有新的組件部署到 bin\ 目錄下時,被動態載入的組件會先被複製到一個稱為「陰影複製快取目錄」下,預設該目錄應該會放在 ASP.NET 的 Temporary ASP.NET Files 目錄下,然後 ASP.NET 的 AppDomain 會直接從這個目錄載入組件進並執行。這個機制最主要的目的是為了讓 bin\ 目錄下的組件不被鎖定,以便於網站在運作的同時也能隨時更新 bin\ 目錄下的組件,並重複 陰影複製(Shadow Copy) 的過程。

我所遇到的情況是更新的組件已經成功被複製進 bin\ 目錄,但網頁並沒有反應更新後的功能,然後畫面就出現「當該檔案已經存在時,無法建立或陰影複製」這個錯誤訊息,這時只要強制回收應用程式集區就會回復正常。

而這台客戶提供的主機與我以往所部署過的主機相比,最主要的差別在於該主機是 Windows Server 2008 並啟用 UAC 機制(客戶要求不能關閉),由於該狀況為偶發,一星期也才發生三、四次,而且是在平凡更新程式的情況下遇到的,所以我不太確定是否跟 UAC 有直接關係,這也是我第一次預到這種錯誤。

Microsoft Connect 網站查到的解決方案很多,不過官方的回應是「已解決:不修正」,但也有蠻多人提到可以透過修改 web.config 避免此問題發生,如果你經常在開發環境遇到此問題,建議可參考以下設定:

<system.web>
<hostingEnvironment shadowCopyBinAssemblies="false" />
</system.web>

透過上述設定可關閉 ASP.NET 的 hostingEnvironment 的 陰影複製(Shadow Copy) 功能,雖然可避免此問題發生,但你很有可能就無法很順利的更新 bin\ 目錄下的檔案了,因為檔案很可能會被鎖定!

所以我最後的解決方法也是「不修正」,因為日後在正式機上更新組件較不頻繁,所以應該沒必要為此做出修正,真的下次遇到問題只要將應用程式集區回收即可。

相關連結