Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
105 views
in Technique[技术] by (71.8m points)

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

I also posted this question on the microsoft forums: https://docs.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.

enter image description here

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?
question from:https://stackoverflow.com/questions/65940019/different-nuget-packages-loaded-when-using-msbuild-than-building-using-visual-st

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

enter image description here

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

enter image description here

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

enter image description here

I used dotnet 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.

enter image description here

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 dotnet Restore Command.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...