如何解决使用 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 文件除外)不会以任何方式更改。
正如您在图像中看到的,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有一些问题,需要修复。
我已将此问题报告给团队。请参阅 one 和 two。如果我没有详细描述问题,您可以关注问题、投票并添加任何评论。
由于这个过程可能需要很长时间,现在,你必须使用我的解决方法,放弃VS IDE还原并更改为使用还原命令:
1) 进入 Tools-->Options-->Nuget Package Manager 并取消选中这两个选项以防 vs ide 后端继续使用 ide restore 来执行错误的行为。
2) 右键单击 Project Properties-->Build Event--> 在 下添加 dotnet restore
>预构建事件命令行。
3)关闭VS,删除项目的bin
和obj
文件夹,然后在VS上重启你的项目,点击Rebuild得到你想要什么。
更新 1
我觉得这个问题很奇怪。我认为问题在于:
<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />
是最后一项,没有条件。它也适用于 net5.0-windows
和 11.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,when
和 if,else
一样,只会根据条件执行一个项目,但是您提供的第一个代码不一样,它们是两个 PackageReference 包含的项目,并且MSBuild 会同时执行它们,当它执行第二行时,它适用于 net5.0-windows
和 netcoreapp3.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.1
而 12.0.3
只有 netcoreapp3.1
。
我在 msbuild 下使用了 11.0.1
。但它使用第一个包含 nuget 版本。 dotnet restore
使用 net5.0-windows
,11.0.1
使用 netcoreapp3.1
。
当我在下面使用 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 的评论中所说,使用选择/何时将解决该问题。
无论如何,我会将此标记为已回答,直到出现更好的答案。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。