简体   繁体   中英

Different nuget-packages loaded when using MSBuild than building using Visual Studio

I also posted this question on the microsoft forums: https://learn.microsoft.com/en-us/answers/questions/249621/different-nuget-packages-are-used-when-compiling-u.html

Consider following.csproj file:

 <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>

Except for the files generated by visual studio when creating the project, there are no other files in this project. The generated files (except the.csproj file) are not altered in any way.

在此处输入图像描述

As you can see in the image, visual studio will - for both projects - reference the 11.0.1 version, and also build the executables using the 11.0.1 version.

When using the Command Line with MSBuild

<msbuildpath> <projectpath> /restore

The executables will be generated with the 12.0.3 version for the .net5.0 target and with the 11.0.1 version for the other target(s)

When using nuget.exe /restore from the command line it will also generate the assets file to use 12.0.3 for .net5.0 and 11.0.1 for the other targets.

Why is there a difference between the packages using visual studio and nuget/msbuild? Is this expected behavior or is this a bug?

*As a side note, the problem does fix itself when using choose/when tags

<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>
  • No matter which build-method generates the correct output, i would expect for MSBuild and VS to generate the same output. Or am i wrong?
  • Why is there a difference between the packages using visual studio and nuget/msbuild?
  • Is this expected behavior or is this a bug?

Please see the update first.

It is quite different between VS IDE Restore and nuget restore , msbuild -t:Restore command line.

And this is not the first issue which I met between VS IDE Restore and command line restore before. See this issue which I raised a few days before .

The main problem is that the VS IDE Restore has a bit more problems and need to be fixed.

I have reported the issue to the Team. See one and two . You can follow the issues, vote it and add any comments if I did not describe the issue in detail.

Since the process might take a long time, for now, you have to use my workaround, abandon VS IDE restore and change to use restore command:

1) enter Tools --> Options --> Nuget Package Manager and uncheck these two options in case the vs ide backend keeps using ide restore to perform the wrong behavior.

在此处输入图像描述

2) right-click on the Project Properties --> Build Event --> add do.net restore under Pre-build event command line .

在此处输入图像描述

3) close VS, delete bin and obj folder of the project and then restart your project on VS, click Rebuild to get what you want.

update 1

I think the problem is quite strange. I think the problem is that:

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

is the last item and has no condition. And it also suitable for net5.0-windows and 11.0.1 version is also included because it is in the last line of the item.

So you should change to use this:

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

Make the condition at the last.

Or

<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>

Give each item a condition(like choose, when ) to avoid the targetframework.net5.0 including the nuget package twice so that it will not lead the complex situation.

But choose, when like if, else , will only execute one item based on the condition but your first provided code is not the same and those are two PackageReference include items, and MSBuild will execute both of them and when it executes the second line, it is suitable for both net5.0-windows and netcoreapp3.1 , so 11.0.1 version will be included for net5.0-windows . That is normal.

Important Analysis

The problem is that , VS IDE Restore will only show the version of the last PackageReference include item and use that version.

In your side , these are what you used:

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

Since the 11.0.1 is the last include, so it always shows 11.0.1 . But Restore Command line is different and it only shows the first PackageReference include node. In your side, if you use do.net Restore Command line , it will use the first node 12.0.3 . And it ignores the second line although it is true for it.

This is my environment:

In this situation , net5.0-windows has two include, in order is 11.0.1 , 12.0.3 while netcoreapp3.1 only has 11.0.1 .

在此处输入图像描述

I used do.net restore below under the msbuild. But it uses the first include nuget version. net5.0-windows uses 11.0.1 and netcoreapp3.1 uses 11.0.1 .

在此处输入图像描述

When I used VS IDE Restore below, it uses the last include PackageReference nuget version.

net5.0-windows uses 12.0.3 version and netcoreapp3.1 uses 11.0.1 version.

So what I am curious why this behavior is different between VS IDE Restore and do.net Restore Command .

So apparently Visual Studio doesn't handle conditions in MSBuild scripts the way MSBuild does it and therefore produces other result. I couldn't find any information on whether or not they will fix this. Probably not as this is already going on since VS2010 according to this post. https://medium.com/@corradocavalli/msbuild-conditions-and-visual-studio-6c5c9347cccf

As @Kit says in the comments on OP using Choose/When will resolve the issue. Anyway i'll mark this as answered until a better answer comes up.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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