使用 MSBuild 时加载的 nuget 包与使用 Visual Studio 构建时不同

问题描述

我也在微软论坛上发布了这个问题: https://docs.microsoft.com/en-us/answers/questions/249621/different-nuget-packages-are-used-when-compiling-u.html

考虑以下 .csproj 文件

 <Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
   <PropertyGroup>
     <OutputType>WinExe</OutputType>
     <TargetFrameworks>netcoreapp3.1;net5.0-windows</TargetFrameworks>
     <UseWPF>true</UseWPF>
   </PropertyGroup>
    
     <ItemGroup>
         <packagereference Include="Newtonsoft.Json" Version="12.0.3" Condition="'$(TargetFramework)' == 'net5.0-windows'"/>
         <packagereference Include="Newtonsoft.Json" Version="11.0.1" />
     </ItemGroup>
 </Project>

这个项目中除了visual studio在创建项目时生成文件外,没有其他文件生成文件(.csproj 文件除外)不会以任何方式更改。

enter image description here

正如您在图像中看到的,visual studio 将 - 对于这两个项目 - 引用 11.0.1 版本,并使用 11.0.1 版本构建可执行文件

在 MSBuild 中使用命令行时

<msbuildpath> <projectpath> /restore

将使用 .net5.0 目标的 12.0.3 版本和其他目标的 11.0.1 版本生成可执行文件

当从命令行使用 nuget.exe /restore 时,它​​还会生成资产文件,以将 12.0.3 用于 .net5.0,将 11.0.1 用于其他目标。

为什么使用 Visual Studio 和 nuget/msbuild 的软件包之间存在差异? 这是预期的行为还是错误

*作为旁注,问题在使用选择/何时标签时会自行解决

<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
   <PropertyGroup>
     <OutputType>WinExe</OutputType>
     <TargetFrameworks>netcoreapp3.1;net5.0-windows</TargetFrameworks>
     <UseWPF>true</UseWPF>
   </PropertyGroup>
    
     <Choose>
         <When Condition="'$(TargetFramework)' == 'net5.0-windows'">
             <ItemGroup>
                 <packagereference Include="Newtonsoft.Json" Version="12.0.2" />
             </ItemGroup>
         </When>
         <Otherwise>
             <ItemGroup>
                 <packagereference Include="Newtonsoft.Json" Version="11.0.1" />
             </ItemGroup>
         </Otherwise>
     </Choose>
 </Project>
  • 无论哪种构建方法生成正确的输出,我都希望 MSBuild 和 VS 生成相同的输出。还是我错了?
  • 为什么使用 Visual Studio 和 nuget/msbuild 的软件包之间存在差异?
  • 这是预期行为还是错误

解决方法

请先查看更新。

VS IDE Restore 和 nuget restore,msbuild -t:Restore 命令行有很大不同。

这不是我之前在 VS IDE 还原和命令行还原之间遇到的第一个问题。 See this issue which I raised a few days before

主要问题是VS IDE Restore有一些问题,需要修复。

我已将此问题报告给团队。请参阅 onetwo。如果我没有详细描述问题,您可以关注问题、投票并添加任何评论。

由于这个过程可能需要很长时间,现在,你必须使用我的解决方法,放弃VS IDE还原并更改为使用还原命令:

1) 进入 Tools-->Options-->Nuget Package Manager 并取消选中这两个选项以防 vs ide 后端继续使用 ide restore 来执行错误的行为。

enter image description here

2) 右键单击​​ Project Properties-->Build Event--> 在 下添加 dotnet restore >预构建事件命令行

enter image description here

3)关闭VS,删除项目的binobj文件夹,然后在VS上重启你的项目,点击Rebuild得到你想要什么。

更新 1

我觉得这个问题很奇怪。我认为问题在于:

 <PackageReference Include="Newtonsoft.Json" Version="11.0.1" />

是最后一项,没有条件。它也适用于 net5.0-windows11.0.1 版本,因为它位于项目的最后一行。

所以你应该改用这个:

<ItemGroup>
        <PackageReference Include="Newtonsoft.Json" Version="11.0.1" />
        <PackageReference Include="Newtonsoft.Json" Version="12.0.3" Condition="'$(TargetFramework)' == 'net5.0-windows'" />
</ItemGroup>

最后设置条件。

<ItemGroup>
        <PackageReference Include="Newtonsoft.Json" Version="11.0.1" Condition="'$(TargetFramework)' == 'netcoreapp3.1'"/>
        <PackageReference Include="Newtonsoft.Json" Version="12.0.3" Condition="'$(TargetFramework)' == 'net5.0-windows'" />
</ItemGroup>

每个项目一个条件(如choose,when)以避免targetframework net5.0包括两次nuget包,以免导致复杂的情况。

但是 choose,whenif,else 一样,只会根据条件执行一个项目,但是您提供的第一个代码不一样,它们是两个 PackageReference 包含的项目,并且MSBuild 会同时执行它们,当它执行第二行时,它适用于 net5.0-windowsnetcoreapp3.1,因此 11.0.1 版本将包含在 { {1}}。这是正常的。

重要分析

问题是VS IDE 还原只会显示最后一个PackageReference包含项的版本并使用该版本。 >

在你身边,这些是你使用的:

net5.0-windows

由于 <ItemGroup> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" Condition="'$(TargetFramework)' == 'net5.0-windows'"/> <PackageReference Include="Newtonsoft.Json" Version="11.0.1" /> </ItemGroup> 是最后一个包含,所以它总是显示 11.0.1。但Restore Command line 不同,它只显示第一个 PackageReference 包含节点。在您这边,如果您使用 dotnet 还原命令行,它将使用第一个节点 11.0.1。它忽略了第二行,尽管它确实如此。

这是我的环境:

在这种情况下12.0.3有两个包含,顺序是 net5.0-windows,11.0.112.0.3 只有 netcoreapp3.1

enter image description here

我在 msbuild 下使用了 11.0.1。但它使用第一个包含 nuget 版本。 dotnet restore 使用 net5.0-windows11.0.1 使用 netcoreapp3.1

enter image description here

当我在下面使用 VS IDE 还原时,它使用最后一个包含 PackageReference nuget 版本。

11.0.1 使用 net5.0-windows 版本,12.0.3 使用 netcoreapp3.1 版本。

所以我很好奇为什么这种行为在 VS IDE 还原dotnet 还原命令 之间有所不同。

,

显然,Visual Studio 没有像 MSBuild 那样处理 MSBuild 脚本中的条件,因此会产生其他结果。我找不到有关他们是否会解决此问题的任何信息。根据这篇文章,可能不是因为自 VS2010 以来这已经发生了。 https://medium.com/@corradocavalli/msbuild-conditions-and-visual-studio-6c5c9347cccf

正如@Kit 在关于 OP 的评论中所说,使用选择/何时将解决该问题。 无论如何,我会将此标记为已回答,直到出现更好的答案。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...