Visual studio 为什么使用一个版本的MSBuild生成时会从另一个版本的MSBuild中查找程序集时出错?

Visual studio 为什么使用一个版本的MSBuild生成时会从另一个版本的MSBuild中查找程序集时出错?,visual-studio,.net-core,msbuild,visual-studio-2019,microsoft.build,Visual Studio,.net Core,Msbuild,Visual Studio 2019,Microsoft.build,我的代码库包含大约30个解决方案。这些解决方案中的大多数项目都是(C#).NET Framework,但最近我添加了一些.NET标准2.0和.NET核心3.1项目。所有解决方案中的所有项目在VisualStudio2019中都能完美构建-只需单击“构建”即可构建 所有解决方案中的所有项目都是在Azure DevOps中构建的(…尽管配置构建管道以达到这一点非常痛苦) 为了方便起见,我编写了一个简单的工具,该工具将使用Microsoft.Build NuGet包循环遍历代码库中的所有解决方案并构建

我的代码库包含大约30个解决方案。这些解决方案中的大多数项目都是(C#).NET Framework,但最近我添加了一些.NET标准2.0和.NET核心3.1项目。所有解决方案中的所有项目在VisualStudio2019中都能完美构建-只需单击“构建”即可构建

所有解决方案中的所有项目都是在Azure DevOps中构建的(…尽管配置构建管道以达到这一点非常痛苦)

为了方便起见,我编写了一个简单的工具,该工具将使用Microsoft.Build NuGet包循环遍历代码库中的所有解决方案并构建它们。这将允许我快速检查我是否在一个解决方案中进行了任何更改,而在另一个解决方案中(例如,在共享项目中)发生了中断,而我没有注意到。这就是麻烦开始的地方

.NET Framework项目都构建良好。然而,在构建任何.NET核心项目时,我都会遇到构建错误。每个项目的情况略有不同,但都包含一些类似于以下内容的错误:

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VisualStudio\v16.0\VSSDK\Microsoft.VsSDK.targets(583,5):
   error MSB4018: System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Build, Version=14.0.0.0, 
   Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies.
   The system cannot find the file specified.
在某些情况下,它可能是Microsoft.Build.Framework而不是Microsoft Build,也可能是版本15.0.0.0而不是14.0.0.0,并且由于找不到它要查找的程序集,因此还会出现其他错误;但这似乎是问题的核心

Microsoft.Build Nuget软件包的版本为16.7.0。唯一安装的MSBuild版本是随Visual Studio 2019版本16.7.6一起安装的版本,我认为是16.7.0。没有一个受影响的项目明显依赖于旧版本的MSBuild,例如,在项目中,它们的ToolsVersion=“16.0”,而且无论如何,如果项目出现问题,它不会在Visual Studio中生成-更不用说,其中一些是最近几天才出现的全新版本


那么,当我使用当前版本的Microsoft.Build程序集进行构建,并且项目都是正确的,并且它们都在Visual Studio中生成时,为什么有些东西(?)决定查找旧版本的Microsoft.Build程序集(并且失败)?或者-我怎样才能自己发现这一点呢?

这是正常的,因为构建复杂项目(及其依赖项)会将许多MSBuild扩展加载到内存中,而这些扩展可能依赖于另一个(通常较旧)版本的MSBuild程序集

这正是Microsoft的
MSBuild.exe.config
包含如下程序集重定向的原因(您也应该这样做)



您是否对VS2019使用了开发者命令提示符或配置了路径?您应该检查
msbuild.exe
的完整路径。它似乎在寻找vs2017。也许你可以尝试将你的
microsoft.build.dll
注册到GAC中。查找microsoft.build.dll 15.1.0.0,然后使用中的方法。谢谢您的评论。我没有使用开发人员命令提示符,也没有使用msbuild.exe-我使用的是应用程序内置的NuGet包中的Microsoft.Build程序集。(我特别不希望必须在文件系统中的某个位置查找并选择msbuild.exe文件,因为这可能会有所不同。我正在使用我的应用程序引用的程序集。)(我不清楚您是否建议将程序集重定向放在我自己的.exe.config中,因为我没有使用MSBuild.exe.config)我可以确认这是有效的,谢谢。令我惊讶的是,Microsoft.Build NuGet包中没有提到这一点,但它就在那里。作为参考,我只需要重定向Microsoft.Build、Microsoft.Build.Framework、Microsoft.Build.Tasks.Core和Microsoft.Build.Utilities.Core(因为它们都在NuGet包中)。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="msbuildToolsets" type="Microsoft.Build.Evaluation.ToolsetConfigurationSection, Microsoft.Build, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  </configSections>
  <startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
  </startup>
  <runtime>
    <DisableFXClosureWalk enabled="true" />
    <DeferFXClosureWalk enabled="true" />
    <generatePublisherEvidence enabled="false" />
    <AppContextSwitchOverrides value="Switch.System.Security.Cryptography.UseLegacyFipsThrow=false" />
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Build.Framework" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" />
        <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="15.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Build" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" />
        <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="15.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Build.Conversion.Core" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" />
        <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="15.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Build.Tasks.Core" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" />
        <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="15.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Build.Utilities.Core" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" />
        <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="15.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Build.Engine" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" />
        <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="15.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Build.Conversion.Core" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" />
        <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="15.1.0.0" />
      </dependentAssembly>
      <!-- Redirects for components dropped by Visual Studio -->
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Activities.Build" culture="neutral" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="4.0.0.0" newVersion="16.0.0.0" />
        <codeBase version="16.0.0.0" href=".\amd64\Microsoft.Activities.Build.dll" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="XamlBuildTask" culture="neutral" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="4.0.0.0-16.0.0.0" newVersion="16.0.0.0" />
        <codeBase version="16.0.0.0" href=".\amd64\XamlBuildTask.dll" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Build.CPPTasks.Common" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" />
        <bindingRedirect oldVersion="16.0.0.0-16.7.0.0" newVersion="16.7.0.0" />
        <codeBase version="16.7.0.0" href="..\..\Microsoft\VC\v160\Microsoft.Build.CPPTasks.Common.dll" />
      </dependentAssembly>
      <!-- Workaround for crash in C++ CodeAnalysis scenarios due to https://github.com/Microsoft/msbuild/issues/1675 -->
      <dependentAssembly>
        <assemblyIdentity name="FxCopTask" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" />
        <codeBase version="16.0.0.0" href="..\..\Microsoft\VisualStudio\v16.0\CodeAnalysis\FxCopTask.dll" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.VisualStudio.CodeAnalysis" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" />
        <codeBase version="16.0.0.0" href="..\..\Microsoft\VisualStudio\v16.0\CodeAnalysis\Microsoft.VisualStudio.CodeAnalysis.dll" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.VisualStudio.CodeAnalysis.Sdk" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" />
        <codeBase version="16.0.0.0" href="..\..\Microsoft\VisualStudio\v16.0\CodeAnalysis\Microsoft.VisualStudio.CodeAnalysis.Sdk.dll" />
      </dependentAssembly>
    </assemblyBinding>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
      </dependentAssembly>
    </assemblyBinding>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
      </dependentAssembly>
    </assemblyBinding>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
      </dependentAssembly>
    </assemblyBinding>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <!-- To define one or more new toolsets, add an 'msbuildToolsets' element in this file. -->
  <msbuildToolsets default="Current">
    <toolset toolsVersion="Current">
      <property name="MSBuildToolsPath" value="$([MSBuild]::GetCurrentToolsDirectory())" />
      <property name="MSBuildToolsPath32" value="$([MSBuild]::GetToolsDirectory32())" />
      <property name="MSBuildToolsPath64" value="$([MSBuild]::GetToolsDirectory64())" />
      <property name="MSBuildSDKsPath" value="$([MSBuild]::GetMSBuildSDKsPath())" />
      <property name="FrameworkSDKRoot" value="$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\NETFXSDK\4.8@InstallationFolder)" />
      <property name="MSBuildRuntimeVersion" value="4.0.30319" />
      <property name="MSBuildFrameworkToolsPath" value="$(SystemRoot)\Microsoft.NET\Framework\v$(MSBuildRuntimeVersion)\" />
      <property name="MSBuildFrameworkToolsPath32" value="$(SystemRoot)\Microsoft.NET\Framework\v$(MSBuildRuntimeVersion)\" />
      <property name="MSBuildFrameworkToolsPath64" value="$(SystemRoot)\Microsoft.NET\Framework64\v$(MSBuildRuntimeVersion)\" />
      <property name="MSBuildFrameworkToolsRoot" value="$(SystemRoot)\Microsoft.NET\Framework\" />
      <property name="SDK35ToolsPath" value="$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx35Tools-x86', 'InstallationFolder', null, RegistryView.Registry32))" />
      <property name="SDK40ToolsPath" value="$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\NETFXSDK\4.8\WinSDK-NetFx40Tools-x86', 'InstallationFolder', null, RegistryView.Registry32))" />
      <property name="WindowsSDK80Path" value="$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.1@InstallationFolder)" />
      <property name="VsInstallRoot" value="$([MSBuild]::GetVsInstallRoot())" />
      <property name="MSBuildToolsRoot" value="$(VsInstallRoot)\MSBuild" />
      <property name="MSBuildExtensionsPath" value="$([MSBuild]::GetMSBuildExtensionsPath())" />
      <property name="MSBuildExtensionsPath32" value="$([MSBuild]::GetMSBuildExtensionsPath())" />
      <property name="RoslynTargetsPath" value="$([MSBuild]::GetToolsDirectory32())\Roslyn" />
      <!-- VC Specific Paths -->
      <property name="VCTargetsPath" value="$([MSBuild]::ValueOrDefault('$(VCTargetsPath)','$(MSBuildExtensionsPath32)\Microsoft\VC\v160\'))" />
      <property name="VCTargetsPath14" value="$([MSBuild]::ValueOrDefault('$(VCTargetsPath14)','$([MSBuild]::GetProgramFiles32())\MSBuild\Microsoft.Cpp\v4.0\V140\'))" />
      <property name="VCTargetsPath12" value="$([MSBuild]::ValueOrDefault('$(VCTargetsPath12)','$([MSBuild]::GetProgramFiles32())\MSBuild\Microsoft.Cpp\v4.0\V120\'))" />
      <property name="VCTargetsPath11" value="$([MSBuild]::ValueOrDefault('$(VCTargetsPath11)','$([MSBuild]::GetProgramFiles32())\MSBuild\Microsoft.Cpp\v4.0\V110\'))" />
      <property name="VCTargetsPath10" value="$([MSBuild]::ValueOrDefault('$(VCTargetsPath10)','$([MSBuild]::GetProgramFiles32())\MSBuild\Microsoft.Cpp\v4.0\'))" />
      <property name="AndroidTargetsPath" value="$(MSBuildExtensionsPath32)\Microsoft\MDD\Android\V150\" />
      <property name="iOSTargetsPath" value="$(MSBuildExtensionsPath32)\Microsoft\MDD\iOS\V150\" />
      <projectImportSearchPaths>
        <searchPaths os="windows">
          <property name="MSBuildExtensionsPath" value="$(MSBuildProgramFiles32)\MSBuild" />
          <property name="MSBuildExtensionsPath32" value="$(MSBuildProgramFiles32)\MSBuild" />
          <property name="MSBuildExtensionsPath64" value="$(MSBuildProgramFiles32)\MSBuild" />
          <property name="VSToolsPath" value="$(MSBuildProgramFiles32)\MSBuild\Microsoft\VisualStudio\v$(VisualStudioVersion)" />
        </searchPaths>
      </projectImportSearchPaths>
    </toolset>
  </msbuildToolsets>
</configuration>