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

时间:2016-04-15 17:02:15

标签: c# nuget

我有一个C#项目(ProjectA),它在一个单独的进程中调用另一个C#项目(ProjectB)。构建输出目录结构是:

/ProjectA.exe
/ProjectB/ProjectB.exe

ProjectA和ProjectB引用相同程序集的差异版本,在本例中为Newtonsoft.Json.dll。

通过向ProjectA添加ProjectB的nuget包来实现构建输出目录结构。 ProjectA和ProjectB在单独的解决方案中并单独构建。 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>

我的问题是ProjectA引用了ProjectB nuget包/ build目录中较新的Newtonsoft.Json.dll,而不是ProjectA解决方案中较旧的Newtonsoft.Json.dll。它们是不同的版本,因此这会在运行时导致问题。我意识到我可以在ProjectA解决方案中更新Newtonsoft.Json.dll的版本,但我希望能够在不可能的情况下解决更一般的情况。如何防止Visual Studio找到错误的Newtonsoft.Json.dll?

2 个答案:

答案 0 :(得分:0)

编辑:这个答案实际上并不奏效。 VisualStudio的行为与它决定使用哪个程序集非常不一致。有时从输出目录中删除程序集将导致最终使用的程序集版本发生更改。显然,任何链接到项目的程序集文件都可以在编译期间由MSBuild选择。请改为查看我的other answer

我发现如果我将所有ProjectB程序集放在nuget package / build目录的单独子目录中,那么MSBuild将不会将它们用作引用。 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>

显然,MSBuild在与ProjectB.targets文件相同的目录中查找匹配程序集,但不查找子目录。这&#34;魔术&#34; MSBuild的行为应该由Microsoft修复。请参阅相关的comment to this question

答案 1 :(得分:0)

最后,将链接的项目组添加到所有ProjectB程序集总是会导致将错误的程序集版本引入ProjectA时出现问题。我不得不求助于robocopy postbuild命令来做我想做的事。这有一个缺点,即当ProjectA被另一个项目引用时,ProjectB程序集不会被复制,但这对我来说并不重要。如果Microsoft修复了this behavior with magic assembly paths,那么原始问题中的nuget包应该可以正常工作。以下是带有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>