简体   繁体   English

Visual Studio错误地从nuget包/构建目录引用程序集

[英]Visual Studio incorrectly referencing assembly from nuget package /build directory

I have a C# project (ProjectA) that invokes another C# project (ProjectB) in a separate process. 我有一个C#项目(ProjectA),它在一个单独的进程中调用另一个C#项目(ProjectB)。 The build output directory structure is: 构建输出目录结构是:

/ProjectA.exe /ProjectA.exe
/ProjectB/ProjectB.exe /ProjectB/ProjectB.exe

ProjectA and ProjectB reference difference versions of the same assembly, in this case Newtonsoft.Json.dll. ProjectA和ProjectB引用相同程序集的差异版本,在本例中为Newtonsoft.Json.dll。

The build output directory structure is achieved by adding a nuget package for ProjectB to ProjectA. 通过向ProjectA添加ProjectB的nuget包来实现构建输出目录结构。 ProjectA and ProjectB are in separate solutions and built separately. ProjectA和ProjectB在单独的解决方案中并单独构建。 The nuget package for ProjectB was created with the following .nuspec and .targets. ProjectB的nuget包是使用以下.nuspec和.targets创建的。

<?xml version="1.0"?>
<package>
  <metadata>
    <id>ProjectB</id>
    <version>$version$</version>
    <title>ProjectB</title>
    <authors>me</authors>
    <owners>me</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>ProjectB</description>
    <copyright>Copyright 2016</copyright>
    <tags>ProjectB</tags>
  </metadata>
  <files>
    <file src="x64\Release\*" target="build" />
    <file src="ProjectB.targets" target="build/ProjectB.targets" /> 
  </files>
</package>  

.

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <NativeLibs Include="$(MSBuildThisFileDirectory)*" />
    <Content Include="@(NativeLibs)">
      <Link>ProjectB\%(FileName)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
</Project>

My problem is that ProjectA is referencing the newer Newtonsoft.Json.dll from the ProjectB nuget package /build directory instead of the older Newtonsoft.Json.dll that is part of the ProjectA solution. 我的问题是ProjectA引用了ProjectB nuget包/ build目录中较新的Newtonsoft.Json.dll,而不是ProjectA解决方案中较旧的Newtonsoft.Json.dll。 They are different versions so this is causing a problem at runtime. 它们是不同的版本,因此这会在运行时导致问题。 I realize I could just update the version of Newtonsoft.Json.dll in the ProjectA solution, but I want to be able to solve the more general case when that is not possible. 我意识到我可以在ProjectA解决方案中更新Newtonsoft.Json.dll的版本,但我希望能够在不可能的情况下解决更一般的情况。 How can I prevent Visual Studio from finding the wrong Newtonsoft.Json.dll? 如何防止Visual Studio找到错误的Newtonsoft.Json.dll?

EDIT: This answer doesn't actually work. 编辑:这个答案实际上没有用。 VisualStudio's behavior is very inconsistent with regard to which assembly it decides to use. VisualStudio的行为与它决定使用哪个程序集非常不一致。 Sometimes removing the assembly from the output directory will cause a change in the version of the assembly that ends up getting used. 有时从输出目录中删除程序集将导致最终使用的程序集版本发生更改。 Apparently any assembly files that are linked to the project can be chosen by MSBuild during compile time. 显然,任何链接到项目的程序集文件都可以在编译期间由MSBuild选择。 See my other answer instead. 请改为查看我的其他答案

I discovered that if I put all the ProjectB assemblies inside a separate subdirectory of the nuget package /build directory then MSBuild will not use them as references. 我发现如果我将所有ProjectB程序集放在nuget package / build目录的单独子目录中,那么MSBuild将不会将它们用作引用。 The working nuget package for ProjectB was created with the following .nuspec and .targets. ProjectB的工作nuget包是使用以下.nuspec和.targets创建的。

<?xml version="1.0"?>
<package>
  <metadata>
    <id>ProjectB</id>
    <version>$version$</version>
    <title>ProjectB</title>
    <authors>me</authors>
    <owners>me</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>ProjectB</description>
    <copyright>Copyright 2016</copyright>
    <tags>ProjectB</tags>
  </metadata>
  <files>
    <file src="x64\Release\*" target="build/ProjectB" />
    <file src="ProjectB.targets" target="build/ProjectB.targets" /> 
  </files>
</package>  

.

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <NativeLibs Include="$(MSBuildThisFileDirectory)ProjectB\*" />
    <None Include="@(NativeLibs)">
      <Link>ProjectB\%(FileName)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>

Apparently, MSBuild is looking in the same directory as the ProjectB.targets file for matching assemblies, but not subdirectories. 显然,MSBuild在与ProjectB.targets文件相同的目录中查找匹配程序集,但不查找子目录。 This "magic" behavior from MSBuild should really be fixed by Microsoft. MSBuild的这种“神奇”行为应该由Microsoft修复。 See related comment to this question 请参阅此问题的相关评论

In the end adding the linked item group with all the ProjectB assemblies was always causing problems with pulling in the wrong assembly version into ProjectA. 最后,将链接的项目组添加到所有ProjectB程序集总是会导致将错误的程序集版本拉入ProjectA时出现问题。 I had to resort to a robocopy postbuild command to do what I wanted. 我不得不求助于robocopy postbuild命令来做我想做的事。 This has the downside that the ProjectB assemblies do not get copied when ProjectA is referenced by another project, but that isn't critical for me. 这有一个缺点,即当ProjectA被另一个项目引用时,ProjectB程序集不会被复制,但这对我来说并不重要。 If Microsoft ever fixes this behavior with magic assembly paths then the nuget package in the original question should work fine. 如果Microsoft曾经使用魔术程序集路径修复此行为,那么原始问题中的nuget包应该可以正常工作。 Here are the .nuspec and .targets files with the robocopy workaround. 以下是带有robocopy解决方法的.nuspec和.targets文件。

<?xml version="1.0"?>
<package>
  <metadata>
    <id>ProjectB</id>
    <version>$version$</version>
    <title>ProjectB</title>
    <authors>me</authors>
    <owners>me</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>ProjectB</description>
    <copyright>Copyright 2016</copyright>
    <tags>ProjectB</tags>
  </metadata>
  <files>
    <file src="x64\Release\*" target="build/ProjectB" />
    <file src="ProjectB.targets" target="build/ProjectB.targets" /> 
  </files>
</package>  

.

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Target Name="ProjectBCopyTarget" AfterTargets="Build">
        <Exec Command="robocopy /PURGE $(MSBuildThisFileDirectory)ProjectB $(TargetDir)ProjectB || if %ERRORLEVEL% LSS 8 exit 0"/>
    </Target>
</Project>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM