从4.0升级到4.5后,MSBuild无法找到依赖项?

6
我们有一个使用一些脚本调用msbuild.exe来构建的.Net 3.5应用程序。
最近,由于公司范围内的政策,所有计算机都开始自动更新到.Net 4.5,导致我们的构建脚本失败了。
错误信息是它们找不到引用的程序集,就像这样:
error CS0012:类型“System.Drawing.Image”在未引用的程序集中定义。您必须添加对程序集“System.Drawing、Version=2.0.0.0、Culture=neutral、PublicKeyToken=b03f5f7f11d50a3a”的引用。
看起来,在每种情况下,我们尝试构建具有对项目B的引用的项目A,并且项目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文件中已经指定了<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中的抽象类,而ProjectB.BaseClass的其中一个属性是System.Drawing.Image类型。
namespace ProjectA
{
    public class SomeClass : BaseClass { }
}

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

从我在网上阅读的所有内容,以及创建自己的测试项目来看,这意味着ProjectA需要引用才能构建。
但是出于某种原因,在使用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或Visual Studio 2010构建ProjectA而无需参考System.Drawing.Image的答案。
我已经确定我不能轻松地在测试项目中重现该行为,因此我最好的猜测是其配置、构建脚本的某些部分,或者这是一个存在于创建.sln或.csproj文件时的错误,而在新创建的项目中不再存在。

1
从MS PSS开发人员的角度来看,您需要获取一个能够重现问题的简单示例。很有可能当您这样做时,您自己就会看到差异。如果在简化解决方案中仍然无法找到根本原因,则请记录一个支持案例,因为这可能是一个错误(如果是这样的话,故障排除将属于免费支持范畴)。一个提示是,如果它在VS2010中编译通过,在2012中失败了,请检查在模块窗口中加载的DLL版本...祝好运! - Jeremy Thompson
@BartoszKP 如果您查看我的问题历史记录,您会看到更多细节。我删除了它,因为它似乎不相关,但如果您认为它很重要,我可以重新添加它。msbuild.exe脚本是相同的,但是生成的csc.exe有一个区别-一个/highentropyva-标志。它似乎不相关,并且无论我将标志设置为什么或是否包含它,手动运行它时构建仍然失败。生成的csc.exe引用相同,并且不包括对System.Drawing的引用。 - Rachel
5
这与MSBuild无关,改变的是你使用了不同的C#编译器,从版本4改为版本5。我在其他问题中看到过一些初步证据表明它更积极地希望解决间接类型引用的问题。没有确凿的证据,每个人都可以通过显而易见的解决方案来修复它。纠缠于此是愚蠢的,只需添加引用即可。 - Hans Passant
2
@HansPassant 我同意,最好是解决问题。我只是好奇是什么(bug?)让它一开始就能构建。我相信你说的C#编译器已经发生了变化。谢谢。 - Rachel
恭喜 @HansPassant 获得了50万分,我认为你应该将你的评论发布在这里作为答案。 - Jeremy Thompson
显示剩余2条评论
4个回答

1
根据Hans' comment,似乎在C#编译器版本4和版本5之间有一些更改,以解决允许我们在没有适当引用的情况下构建ProjectA的错误。查看msbuild.exe日志时,可以看到它涉及调用csc.exe,其中包含完全相同的/reference列表,但在4.5中失败。使用4.0构建ProjectA。此与MSBuild无关,更改的是您正在使用不同的C#编译器,即5而非4。在其他问题的浅显证据中,我发现它更积极地希望解决间接类型引用。没有任何确定的方案,每个人都只需使用显而易见的解决方案来解决此问题。
任务 "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 SomeFile.cs Properties\VersionInfo.cs Microsoft (R) Visual C# 2010编译器版本4.0.30319.1 版权所有(C) Microsoft Corporation。保留所有权利。
已执行任务 "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 Properties\AssemblyInfo.cs SomeFile.cs Properties\VersionInfo.cs (任务ID:5812) Microsoft (R) Visual C# 编译器版本4.0.30319.18408 (任务ID:5812) (任务ID:5812) 针对 Microsoft (R) .NET Framework 4.5 (任务ID:5812) 版权所有(C) Microsoft Corporation。保留所有权利。 (任务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: (与上一个错误相关的符号位置) (任务ID:5812) 命令以代码1退出。(任务ID:5812) 执行任务"Csc"完成--失败。(任务ID:5812)
我希望这里有人能够解释那是什么,以及我如何在4.0中复现这个“bug”,但看起来这个问题不容易回答。

我们的构建服务器在安装更新后出现了类似的问题。不幸的是,只有当应用程序启动并立即因链接器错误而死亡时,才会显露出这个问题。我发现引用的处理方式已经改变了。如果在VS中添加NuGet引用,则其属性设置为复制本地,但相关的<Private>True</Private>标记未添加到.csproj文件中。在更新之前,引用的程序集仍然被复制到输出目录中;现在它们没有了。传递引用根本没有被复制。 - bstenzel

0

可能是因为更新时未更新您的运行时设置模式,特别是<probing>元素,该元素告诉.Net在哪些路径中搜索程序集:

例如:

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

请参见:http://msdn.microsoft.com/zh-cn/library/microsoft.build.tasks.assignprojectconfiguration.onlyreferenceandbuildprojectsenabledinsolutionconfiguration(v=vs.121).aspx


0

如果我要猜的话,我会说所有无法定位的引用都是版本2.0.0.0。最近我们在这里也遇到了类似的问题,我们不得不更新引用为System.*和mscorlib的4.0.0.0版本以及类似的引用。

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

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


0

Rachel,你升级后的项目中,System.Drawing 的引用是否设置为 SpecificVersion = true

另外,你的库项目中是否使用了预编译的 resx 文件? 尝试右键单击 .resx 文件,然后再次选择“运行自定义工具”以重新生成引用。

最后一次帮助你的尝试是,在主项目配置中使用 useLegacyV2RuntimeActivationPolicy="true",并尝试使用旧版的 System.Drawing 库。


ProjectB 中的 System.Drawing 引用设置为默认值... 在 .csproj 文件中,它只是说 <Reference Include="System.Drawing" />。与非系统引用不同,VS 中没有“特定版本”属性。然而,问题并不在于 ProjectB,而是在于 ProjectA,即使它应该有一个引用到 System.Drawing,但它仍然可以编译通过。此外,我们没有使用任何预编译的 resx 文件,尽管我不确定这是否有影响。我会查找该属性的位置并尝试一下,虽然我认为这并不重要。 - Rachel
我试图使用这篇文章来帮助你。很奇怪,你的msbuild正在尝试使用System.Drawing version = 2.0 - rodrigogq
谢谢提供链接,我也会去查看。我们正在构建针对 .Net 3.5 的应用程序,这就是为什么我们使用 System.Drawing v2.0 的原因。如果我没记错的话,下一个版本是4.0,这将需要我们将整个应用程序更新到4.0,但目前这不是一个选项。 - Rachel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接