【问题标题】:MSBuild can no longer find dependencies after upgrading from 4.0 to 4.5?MSBuild 从 4.0 升级到 4.5 后无法再找到依赖项?
【发布时间】:2014-12-25 16:01:07
【问题描述】:

我们有一个 .Net 3.5 应用程序,它是使用一些调用 msbuild.exe 的脚本构建的

最近,作为全公司政策的一部分,我们所有的机器都开始自动从 .Net 4.0 更新到 .Net 4.5,而且我们的构建脚本开始失败。

给出的错误是他们找不到引用的程序集,如下所示:

错误 CS0012:“System.Drawing.Image”类型在未引用的程序集中定义。 您必须添加对程序集“System.Drawing,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a”的引用。

看起来在每种情况下,我们都尝试构建项目 A 引用项目 B,项目 B 引用库 X,并得到项目 A 需要引用库 X 的错误。

一个临时的解决方法是卸载 4.5,卸载 4.0,然后重新安装 4.0,但是在更新通常是静默和自动的环境中,这是耗时且不实用的。

我已经尝试过使用以下 msbuild 开关,但没有成功

  • /toolsversion:3.5 - 关于 Func 未定义的例外情况
  • /toolsversion:4.0 - 因为 4.5 取代了 4.0 工具,所以无法工作
  • /p:TargetFrameworkVersion="v3.5" - 同样的错误
  • /p:VisualStudioVersion=11.0 - 同样的错误 *` 在 csproj 文件中 - 已经存在,同样的错误

.csproj 文件已经在我的解决方案中的每个 csproj 文件中指定了 <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>ToolsVersion="4.0"

我也试过把TargetFrameworkVersion改成4.0,也不管用。

我在网上找到了一些关于 Microsoft 在 4.0 到 4.5 更新期间将标志 OnlyReferenceAndBuildProjectsEnabledInSolutionConfigurationfalse 更改为 true 的说明,但是在 csproj 文件中手动设置该标志也不能解决问题。

<OnlyReferenceAndBuildProjectsEnabledInSolutionConfiguration>
    false
</OnlyReferenceAndBuildProjectsEnabledInSolutionConfiguration>

为什么从 4.0 升级到 4.5 后 msbuild 找不到这些子程序集,我该如何解决?

更新

我终于找到了问题的根源,但我不知道这是怎么发生的。

ProjectA 有一个类继承自 ProjectB 中的抽象类,ProejctB.BaseClass 的属性之一是 System.Drawing.Image 类型。

namespace ProjectA
{
    public class SomeClass : BaseClass { }
}

namespace ProjectB
{
    public abstract class BaseClass
    {
        public System.Drawing.Image GetImage() { };
    }
}

根据我在网上阅读的所有内容以及创建自己的测试项目,这意味着 ProjectA 需要引用 System.Drawing.Image 才能构建。

但无论出于何种原因,在使用 msbuild 4.0 或在 VS 2010 中构建项目时,此限制似乎对我们的项目无关紧要。构建 ProjectA 而不引用 System.Drawing.Image 非常高兴。

即使在更新到 .Net 4.5 之后,我仍然可以从 Visual Studio 2010 成功构建 ProjectA,而无需添加对 System.Drawing.Image 的引用,但是现在使用 msbuild 构建(正确吗?)失败。在 VS 2012 Express 中构建时,我也遇到了参考错误,因此在新版本的 VS 中显然已经修复了允许这种情况发生的任何问题。

目前,我已经浏览了我们解决方案中的所有 148 个项目并修复了所有引用,但是我想保留这个问题以尝试回答为什么我能够使用 msbuild 4.0 构建 ProjectA 或Visual Studio 2010 没有引用System.Drawing.Image

我已经确定我不能轻易地在测试项目中重现该行为,所以我最好的猜测是它的某些配置、构建脚本的某些部分,或者它是 .sln 或.csproj 文件已创建,并且在新创建的项目中不再存在。

【问题讨论】:

  • 从 MS PSS 开发人员的角度来看,您需要获得一个能够重现该问题的简单示例。当您这样做时,您可能会自己看到增量。如果您仍然没有在基本解决方案中看到根本原因,那么请记录支持案例,因为这有一种错误的味道(如果是,故障排除将得到免费支持)。一个提示是,如果它在 VS2010 中编译并在 2012 年失败,请检查“模块”窗口中加载了哪些版本的 DLL……祝你好运!
  • @JeremyThompson 我一直试图在一个小样本解决方案中重现该问题,但到目前为止还没有运气。该应用程序非常大,几年前,是在我加入团队之前创建的。此外,创建它的原始人不再在我身边问他是否对设置做了任何不寻常的事情。我相信你是对的,它很可能是一个错误,但是也会仔细检查 dll 版本。谢谢。
  • 您是否尝试过阅读 VS2010 构建日志以查看它传递给 MSBuild 的开关以使其编译正常?
  • 这与 MSBuild 没有任何关系,改变的是您使用的是不同的 C# 编译器。版本 5 而不是 4。我在其他问题中看到了粗略的证据,这些证据更积极地想要解决间接类型引用。没有什么可钉在墙上的,每个人都只是用明显的解决方案来解决这个问题。挂断这个是愚蠢的,只需添加参考。
  • @HansPassant 我同意,最好只是解决问题。我只是好奇是什么(错误?)首先允许它构建。不过,我很确定您对 C# 编译器的更改是正确的。谢谢。

标签: c# msbuild .net-3.5 .net-4.5 csc


【解决方案1】:

基于Hans' comment,这听起来像是在版本 4 和版本 5 之间的内部 C# 编译器中发生了一些变化,以修复允许我们在没有正确引用的情况下构建 ProjectA 的错误。

这与 MSBuild 没有任何关系,改变的是您使用的是不同的 C# 编译器。版本 5 而不是 4。我在其他问题中看到了粗略的证据,这些证据更积极地想要解决间接类型引用。没有什么可钉在墙上的,每个人都只是用明显的解决方案来解决这个问题。

查看msbuild.exe 日志时,我可以看到它归结为对csc.exe 的调用,其中包含完全相同的/reference 列表,但是在4.5 中失败。

使用 4.0 构建 ProjectA

任务“Csc” c:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /noconfig /nowarn:1701,1702 /nostdlib+ /errorreport:prompt /warn:4 /define:TRACE /reference:C:\Path\bin\ Release\ProjectB.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\ System.Core.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Data.DataSetExtensions.dll" /reference:C:\Windows\Microsoft.NET\ Framework\v2.0.50727\System.Data.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\ System.Web.Services.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\ v3.5\System.Xml.Linq.dll" /debug:pdbonly /filealign:512 /keyfile:ProjectA.snk /optimize+ /out:obj\Release\ProjectA.dll /target:library Properties\AssemblyInfo.cs SomeF ile.cs 属性\VersionInfo.cs Microsoft (R) Visual C# 2010 编译器版本 4.0.30319.1 版权所有 (C) 微软公司。版权所有。 完成执行任务“Csc”。

使用 4.5 构建 ProjectA

任务“Csc”(任务 ID:5812) C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /noconfig /nowarn:1701,1702 /nostdlib+ /errorreport:prompt /warn:4 /define:TRACE /highentropyva- /reference:C:\Path \bin\Release\ProjectB.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3 .5\System.Core.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Data.DataSetExtensions.dll" /reference:C:\Windows\Microsoft .NET\Framework\v2.0.50727\System.Data.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /reference:C:\Windows\Microsoft.NET\Framework\v2 .0.50727\System.Web.Services.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft \Framework\v3.5\System.Xml.Linq.dll" /debug:pdbonly /filealign:512 /keyfile:ProjectA.snk /optimize+ /out:obj\Release\ProjectA.dll /target:library /utf8output Prop erties\AssemblyInfo.cs SomeFile.cs Properties\VersionInfo.cs (TaskId:5812) Microsoft (R) Visual C# 编译器版本 4.0.30319.18408 (TaskId:5812) (任务 ID:5812) 适用于 Microsoft (R) .NET Framework 4.5 (TaskId:5812) 版权所有 (C) 微软公司。版权所有。 (任务 ID:5812) (任务 ID:5812) SomeFile.cs(32,18):错误 CS0012:“System.Drawing.Image”类型在未引用的程序集中定义。您必须添加对程序集“System.Drawing,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a”的引用。 [C:\Path\ProjectA.csproj] c:\Path\bin\Release\ProjectB.dll:(与先前错误相关的符号位置)(TaskId:5812) 该命令以代码 1 退出。 (TaskId:5812) 完成执行任务“Csc”——失败。 (任务 ID:5812)

我希望这里有人能够解释那是什么,以及我如何在 4.0 中重现这个“错误”,但看起来这个问题并不容易回答。

【讨论】:

  • 安装更新后,我们目前在构建服务器上遇到了类似的问题。不幸的是,这个问题只有在应用程序启动并立即死于链接器错误时才会变得明显。我发现处理引用的方式已经改变。如果在 VS 中添加 NuGet 引用,其属性设置为复制本地,但相关的 True 标记不会添加到 .csproj 文件中。无论如何,在更新之前,引用的程序集都被复制到了输出目录;现在他们不是了。传递引用根本不会被复制。
【解决方案2】:

如果我不得不猜测,我会说它无法再找到的所有引用都是 2.0.0.0 版本。我们最近在这里遇到了类似的问题,我们必须将引用更新为 System.* 和 mscorlib 的 4.0.0.0 版本以及类似的引用。

如果您无法替换引用并且无法选择 BindingRedirects,请尝试将 v2.0.0.0 手动添加到您的 bin 文件夹中。

最后,您可以使构建输出详细,以查看它在哪里寻找这些引用,它可能会指导您找到解决方案。

【讨论】:

    【解决方案3】:

    也许当它更新时它不会更新您的运行时设置架构,特别是告诉 .Net 搜索程序集的路径的 &lt;probing&gt; 元素:

    例如。

    <configuration>
       <runtime>
          <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
             <probing privatePath="bin;bin2\subbin;bin3"/>
          </assemblyBinding>
       </runtime>
    </configuration>
    

    见:http://msdn.microsoft.com/en-us/library/microsoft.build.tasks.assignprojectconfiguration.onlyreferenceandbuildprojectsenabledinsolutionconfiguration%28v=vs.121%29.aspx

    【讨论】:

      【解决方案4】:

      Rachel,升级后您的 System.Drawing 项目中是否有任何机会引用设置为 SpecificVersion = true

      另外,您是否在库项目中使用任何预编译的 resx 文件? 尝试右键单击 .resx 文件并再次选择“运行自定义工具”以重做引用。

      对于我最后一次帮助您的尝试,您可以尝试在主项目配置中使用 useLegacyV2RuntimeActivationPolicy="true",并尝试使用旧的 System.Drawing 库。

      【讨论】:

      • ProjectB 中的 System.Drawing 引用设置为任何默认值......在 .csproj 文件中它只是说 &lt;Reference Include="System.Drawing" /&gt;。 VS 中没有像非系统引用那样的“特定版本”属性。 ProjectB 不是问题,它是 ProjectA,它允许在不引用 System.Drawing 的情况下进行编译,即使它应该有一个。此外,我们没有使用任何预编译的 resx 文件,尽管我不确定这有什么关系。我会调查该属性的位置并试一试,尽管我再次认为这无关紧要
      • 我试图帮助使用this article。您的 msbuild 尝试使用 System.Drawing version = 2.0 确实很奇怪。
      • 谢谢你的链接,我也去看看。我们正在为 .Net 3.5 构建,这就是我们使用 System.Drawing v2.0 的原因。如果我没记错的话,下一个版本是 4.0,这将要求我们将整个应用程序更新到 4.0,这目前不是一个选项。
      猜你喜欢
      • 2016-10-26
      • 2020-10-15
      • 1970-01-01
      • 2012-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-24
      相关资源
      最近更新 更多