System.Web.MVC 自 MS14-059 以來未復製到 bin 文件夾中。如何防止由於 Windows 更新而創建缺少 DLL 的建構?
今天早上有報導稱,我們的 QA 伺服器上的 Web 應用程序完全損壞,Web.config 報告了以下錯誤:
無法載入文件或程序集“System.Web.Mvc,Version=5.1.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35”或其依賴項之一。該系統找不到指定的文件
記得看到提到 MVC 的 Windows 更新,我做了一些探勘,發現很多人報告 最近 的Windows 更新破壞了 MVC。
在對這些問題和我們的伺服器進行了大量探勘之後,似乎我們被咬的東西與其他問題中的東西不匹配,但它看起來確實相關。以下是我們認為知道的:
- 我們損壞的應用程序使用 ASP.NET MVC 5.1
- MVC 是通過 NuGet 安裝的
- 我們的 BuildServer 和 QA 伺服器沒有安裝 MVC 5.1(因此,不是 GAC’d)
我們認為已損壞的內容導致創建了“不良建構”:
- 儘管 GAC 中沒有安裝 MVC 5.1,但通過 Windows 更新在 BuildServer 上安裝了 MVC 5.1 的更新檔
- 該更新檔已將 MVC 5.1 的“更新”版本放入 GAC
- 當 DLL 在 GAC 中時,CopyLocal=true 會被忽略;因此,自更新檔以來,這意味著從 BuildServer 建構我們的應用程序的輸出文件夾中不再有 System.Web.MVC
- 由於 System.Web.MVC 不在我們的 QA 伺服器上的 GAC 中(它們尚未打更新檔),因此應用程序現在失敗,因為找不到 System.Web.MVC
假設上述行為是正確的,這意味著任何時候 MS 通過 Windows 更新為我們在 GAC 中沒有的 NuGet DLL 提供服務,我們的 BuildServer 將開始生成不完整的建構(錯過那些已註入 GAC 的 DLL) .
升級到 MVC 5.2 解決了這個問題(可能是因為它沒有打更新檔,因此沒有註入 GAC);DLL 現在被複製到輸出文件夾。升級到 5.2.2 的差異沒有任何變化,除了版本號更改(特別是沒有
<Private>添加/編輯節點)。我們不希望開始對所有內容進行 GAC,也不希望創建手動建構步驟來將我們所有的 DLL 複製到
bin文件夾中,以防萬一 MS 修補它們。那麼,如果 MS 將來修補其他 DLL,我們今天可以改變什麼來確保我們不會最終導致 BuildServer 默默地產生錯誤的建構?
> > 儘管 GAC 中沒有安裝 MVC 5.1,但通過 Windows 更新在 BuildServer 上安裝了 MVC 5.1 的更新檔 > > >
是的,這種行為實際上是設計使然。請參閱<http://blogs.msdn.com/b/dotnet/archive/2014/01/22/net-4-5-1-supports-microsoft-security-updates-for-net-nuget-libraries.aspx>。
> > 該更新檔已將 MVC 5.1 的“更新”版本放入 GAC > > >
對,那是正確的; 這就是更新檔如何讓更新的程式碼而不是舊程式碼執行。請參閱<https://technet.microsoft.com/en-us/library/security/ms14-059>。
> > 當 DLL 在 GAC 中時,CopyLocal=true 會被忽略;因此,自更新檔以來,這意味著從 BuildServer 建構我們的應用程序的輸出文件夾中不再有 System.Web.MVC > > >
不完全是。實際發生的是一個以前是 CopyLocal=true 的項目被切換到 CopyLocal=false。CopyLocal 可以通過以下兩種方式之一進行設置:1) 如果
<Private>True</Private>.csproj 文件中有顯式設置,或 2) 預設情況下,如果不存在此類設置(GAC 的程序集預設不 CopyLocal;其他程序集有)。因此,在這種情況下似乎發生的是您的項目文件在 csproj 文件中沒有此設置。結果,GUI 顯示了基於更新檔之前評估的預設值的設置(CopyLocal = true),但在安裝更新檔之後,GUI 現在將顯示 GAC 程序集的新預設值(CopyLocal = false )。
> > 由於 System.Web.MVC 不在我們的 QA 伺服器上的 GAC 中(它們尚未打更新檔),因此應用程序現在失敗,因為找不到 System.Web.MVC > > >
這是正確的。
> > 假設上述行為是正確的,這意味著任何時候 MS 通過 Windows 更新為我們在 GAC 中沒有的 NuGet DLL 提供服務,我們的 BuildServer 將開始生成不完整的建構(錯過那些已註入 GAC 的 DLL) . > > >
對於沒有明確
<Private>True</Private>設置的任何 .csproj 引用,這是正確的。此外,請注意使用 NuGet 更新您的 MVC 引用可以刪除此設置,即使它以前存在。請參閱<http://nuget.codeplex.com/workitem/4344>。> > 升級到 MVC 5.2 解決了這個問題(可能是因為它沒有打更新檔,因此沒有註入 GAC);DLL 現在被複製到輸出文件夾。升級到 5.2.2 的差異沒有任何變化,除了版本號更改(特別是沒有添加/編輯節點)。 > > >
這是正確的。由於 MVC 5.2 不是 GAC 的,即使沒有顯式
<Private>True</Private>設置,這個非 GAC 程序集的預設值也會是 CopyLocal=true。> > 我們不希望開始對所有內容進行 GAC,也不希望創建手動建構步驟來將我們所有的 DLL 複製到 bin 文件夾中,以防 MS 修補它們。那麼,如果 MS 將來修補其他 DLL,我們今天可以改變什麼來確保我們不會最終導致 BuildServer 默默地產生錯誤的建構? > > >
你今天能做的最好的事情是:
<Private>True</Private>為所有 NuGet 包程序集引用在 .csproj 文件中放置顯式設置。- 在修復 NuGet 錯誤 #4344 之前,只要您使用 NuGet 更新包引用,請返回您的 .csproj 文件並重新添加顯式
<Private>True</Private>設置。