简体   繁体   中英

Why are content files from NuGet packages added as links in .NET Core projects and how can you prevent that?

I am developing a .NET Standard library and plan to use it in both .NET Core and .NET Framework projects. My library is dependant on a third library which itself is dependant on a few C binary files. The C binary files have to be copied to the output directory of the project which will be referencing my library.

I added the binary files to my library project as content and they are copied to the content and contentFiles directories when the NuGet package is packed with the dotnet pack command. The files are also listed in the nuspec file.


However when I install the NuGet package there are two different behaviours to observe depending if I install it to a .NET Framework or .NET Core project:

.NET Framework

The binary files I added to my library project are also added to the referencing project and I can copy them to the output directory. This is the behaviour that I expect, want and works.

.NET Core

The binary files I added to my library project are also added to the referencing project but as links which also works but only on my machine of course since the NuGet packages are stored in the Windows user folder by default. This create problems for anyone else that will work on the same project on a different machine as the links to the files are broken in that case.


I already tried messing around with the nuspec file itself but this doesn't really help since I only get the nuspec file after packing which is done by CI pipeline.

Why is the behaviour for .NET Framework and .NET Core project different in that case and is it possible to get the behaviour of a .NET Framework project in a .NET Core project?

Actually, this is the normal behavior.

And what you saw of content and contentFiles's behavior is normal and the rule of them is designed by Microsoft.

Please refer to this similar issue and this one .

Content node will pack its content as the real files into the main project. This is for Net Framework projects with packages.config nuget management format.

While, ContentFiles node will pack its content as link format into the main project( Net Core and Net Standard projects). This is for PackageReference nuget management format.

So if you want this feature is the same as the Net Framework project on Net Core , you should use a <package_id>.props on net standard projects to get what you want.

Steps

1) create a file called <packages_id>.props file under the build folder on your net standard lib project.

在此处输入图像描述

Note : if your lib nuget is called lib.1.0.0.nupkg , the props file should be named as lib.props file so that it will work. It should be the same as the nuget_id .

2) add these on lib.props file:

<Project>
  <Target Name="CopyFiles" BeforeTargets="Build">
    <ItemGroup>     
      <File Include="$(MSBuildThisFileDirectory)..\Binary\*.*"></File>          
    </ItemGroup>
      <Copy SourceFiles="@(File)" DestinationFolder="$(ProjectDir)Binary"></Copy>
  </Target>
</Project>

3) add these on xxx.csproj file of the lib project.

<ItemGroup>
<None Include="xxx\**.**"(all the binary files) Pack="true" PackagePath="Binary"></None>
<None Include="build\lib.props" Pack="true" PackagePath="build"></None>
</ItemGroup>

4) It will copy the binary files into a folder called Binary into your main project when you install this new version of the nuget package.

Also, when you install this new version of nuget package, please clean your nuget caches or delete all files under C:\Users\xxx(current user)\.nuget\packages .

Besides , there is a similar issue about the steps .

Based on Perry Quian-MSFT 's answer I copied the binary files to the output directory instead of the project.

I think that is a better way than cluttering up a project with unnecessary files.

This is what my props file looks like:

<Project ToolsVersion="4.0" xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
  <ItemGroup>
    <Binaries Include="$(MSBuildThisFileDirectory)..\binaries\*.*" />
  </ItemGroup>

  <Target Name="CopyBinaries" BeforeTargets="Build">
    <Copy SourceFiles="@(Binaries)" DestinationFolder="$(OutDir)" SkipUnchangedFiles="true" />
  </Target>
</Project>

Success that I'd like to share - Am using dotnetcore (.Net 6) I needed to share a c# class library as well as common json config files and created a library class project that includes content files and outputs a nuget package.

Tacking onto the other good answers - here's what worked for me after incorporating the other suggestions.

In the "lib" project - included the build\lib.props file. Contents:

<Project>
    <Target Name="CopyFiles" BeforeTargets="Build">
        <ItemGroup>
            <ConfigFilesShared Include="$(MSBuildThisFileDirectory)..\SharedConfig\*.*" />
        </ItemGroup>
        <Copy SourceFiles="@(ConfigFilesShared)" DestinationFolder="$(ProjectDir)SharedConfig" SkipUnchangedFiles="false"></Copy>
    </Target>
</Project>

The above copies the files into the consuming project's folder prior to build.

Also included the following in the lib.csproj file:

<ItemGroup>
    <Content Include="Config\*" Pack="true" PackagePath="SharedConfig\" />
    <None Include="Build\Roc.Shared.props" Pack="true" PackagePath="build"></None>
</ItemGroup>

In the "consuming" project - to hide the directory of files from the project so as not to make it confusing I have the following in my csproj that is consuming the shared library:

<ItemGroup>
    <Content Remove="SharedConfig\**" />
    <None Remove="SharedConfig\**" />
</ItemGroup>

To ensure that the files though get included in both Output (regular build) and Publish the following code is used.

<!-- For Build - Move the shared library shared config files that were previously copied to the SharedConfig folder-->
<Target Name="PrebuildScriptShared" BeforeTargets="Build">
    <ItemGroup>
        <ConfigFiles1 Include="SharedConfig\**" />
    </ItemGroup>
    <Copy SourceFiles="@(ConfigFiles1)" DestinationFolder="$(OutDir)Config" SkipUnchangedFiles="false" />
</Target>
<!-- For Publish - Move the shared library shared config files that were previously copied to the SharedConfig folder-->
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">
    <ItemGroup>
        <ConfigFiles2 Include="SharedConfig\**" />
    </ItemGroup>
    <Copy SourceFiles="@(ConfigFiles2)" DestinationFolder="$(PublishDir)Config" SkipUnchangedFiles="false" />
</Target>

And Voila , You now have content files that get copied from the the nuget package to your consuming project, and get used during build. debugging and publishing: :)

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