自MS14-059以来,System.Web.MVC不会复制到bin文件夹中。 如何防止由于Windows更新而创build缺lessDLL的生成?

今天早上有报道说,我们的QA服务器上的Web应用程序被完全破坏,从Web.config报告了以下错误:

无法加载文件或程序集“System.Web.Mvc,Version = 5.1.0.0,Culture = neutral,PublicKeyToken = 31bf3856ad364e35”或其某个依赖项。 该系统找不到指定的文件

记住看到提到MVC的Windows Update,我做了一些挖掘,发现很多 人 报告最近的Windows Update中断MVC。

在深入了解这些问题和我们的服务器之后,似乎被咬的东西与其他问题中的东西并不匹配,但确实有关联。 以下是我们所知道的:

  • 我们的应用程序被破坏使用ASP.NET MVC 5.1
  • MVC是通过NuGet安装的
  • 我们的BuildServer和QA服务器没有安装MVC 5.1(因此没有安装GAC)

我们相信已经破裂导致了“糟糕的构build”被创造出来:

  • 尽pipe没有在GAC中安装MVC 5.1,但是通过Windows Update在BuildServer上安装了一个用于MVC 5.1的补丁
  • 该补丁已将MVC 5.1的“更新”版本放入GAC中
  • 当DLL在GAC中时,CopyLocal = true被忽略; 因此,自补丁以来,这意味着从BuildServer生成的应用程序在输出文件夹中不再具有System.Web.MVC
  • 由于System.Web.MVC不在我们的QA服务器的GAC中(它们尚未打补丁),因此应用程序现在失败,因为无法findSystem.Web.MVC

假设上面描述的行为是正确的,这意味着任何时候MS通过Windows Update 为我们没有的GAC中的NuGet DLL提供服务,我们的BuildServer将开始生成不完整的构build(错过了那些已经注入到GAC中的DLL) 。

升级到MVC 5.2解决了这个问题(可能是因为它没有打补丁,所以没有注入到GAC中)。 该DLL现在被复制到输出文件夹。 除了版本号更改(没有添加/编辑<Private>节点)之外,升级到5.2.2的差异没有变化。

我们不希望启动GACing的一切,也不会创build手动构build步骤来将所有的DLL复制到bin文件夹中,以防MS修补它们。

那么,我们今天可以改变什么呢以确保我们不会因为未来的MS修补其他DLL而无声无息地生成回构build错误的BuildServer?

尽pipe没有在GAC中安装MVC 5.1,但是通过Windows Update在BuildServer上安装了一个用于MVC 5.1的补丁

是的,这种行为实际上是由devise。 请参阅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)如果在.csproj文件中有明确的<Private>True</Private>设置,或者2)默认情况下,如果不存在这样的设置(GAC的程序集不会CopyLocal默认情况下,其他程序集)。

所以在这种情况下似乎发生的事情是你的项目文件在csproj文件中没有这个设置。 因此,GUI在修补程序(CopyLocal = true)之前显示了基于评估的默认值的设置,但是在安装修补程序之后,GUI现在将显示GAC的程序集的新默认值(CopyLocal = false )。


由于System.Web.MVC不在我们的QA服务器的GAC中(它们尚未打补丁),因此应用程序现在失败,因为无法findSystem.Web.MVC

这是正确的。


假设上述行为是正确的,这意味着任何时候MS通过Windows Update服务一个NuGet DLL,我们没有在GAC中,我们的BuildServer将开始产生不完整的构build(错过了那些注入到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'd,即使没有明确的<Private>True</Private>设置,这个非GAC'd程序集的默认值将是CopyLocal = true。


我们不希望启动GACing的一切,也不会创build手动构build步骤来将所有的DLL复制到bin文件夹中,以防MS修补它们。 那么,我们今天可以改变什么呢,以确保我们不会因为未来的MS修补其他DLL而无声无息地生成回构build错误的BuildServer?

你今天能做的最好的是:

  1. 在你的.csproj文件中join显式的<Private>True</Private>设置,以获得所有的Nu​​Get包assembly件参考。
  2. 在修复NuGet bug#4344之前,只要您使用NuGet更新软件包引用,请返回到您的.csproj文件并重新添加明确的<Private>True</Private>设置。

我相信这个问题是在.Net Web开发工具和UI博客这里的链接中解决的

我不会在这里重复整件事情,因为这个问题和解决scheme在这方面的解释相当好。

不过要重复一下这些关键点,这应该解释为什么会发生这种情况:

  • 作为修补程序KB2994397的一部分,MVC 5.1已添加到GAC。

  • 似乎有一个NuGet的bug重置CopyLocal标志。 (请参阅链接 )这意味着,当一台机器上面的补丁部署到一个未打补丁的机器将打破!

  • MVC 4的汇编版本号增加了相同的安全更新 – MS14-059(所以GAC版本将不会被使用)这解释了为什么MVC 4版本仍然工作 – 尽pipe它在GAC中。

我在我的博客中添加了关于此问题的注释: Microsoft Asp.Net MVC安全更新MS14-059打破了我的构build! 。

您对问题的分析是正确的,默认情况下,当程序集位于GAC中时,“复制本地”标志设置为false,手动将其设置为true应解决此问题。

升级到5.2.2甚至更好,除了安全修补程序之外,还可以获得新版本的好处。