How to flatten Nuget package contentFiles?

922 views Asked by At

Nuget package issues - buildAction, copyToOutput, flatten are ignored

Package project (ThisProject.vbproj)- .Net Standard Library 2.0, .nuspec file:

<references>
      <reference file="ThisProject.dll"></reference>
      <reference file="First.dll"></reference>
      <reference file="Second.dll"></reference>
      <reference file="...."></reference>
    </references>
    <contentFiles>
      <files include="any/any/*" buildAction="Content" copyToOutput="true" flatten="true" />
    </contentFiles>
  </metadata>
  <files>
    <file src="contentFiles\any\any\First.dll" target="lib\any\any\First.dll"></file>
    <file src="contentFiles\any\any\Second.dll" target="lib\any\any\Second.dll"></file>
   <file src="contentFiles\any\any\....dll" target="lib\any\any\.....dll"></file>
    </files>

When importing in .net ClickOnce Framework 4.6.1 Project, the contentFiles are still in the subfolders (flatten is ignored), Build Action and CopyToOutputDirectory are the defaults (buildAction,copyToOutput are ignored)

Read all the documentation I could find e.g.

https://learn.microsoft.com/en-us/nuget/reference/nuspec

What am I doing wrong?

1

There are 1 answers

0
Mr Qian On

I think you have some misunderstanding about this part.

First, contentFiles works for new-sdk projects(Net Core and Net Standard) with PackageReference nuget management format rather than Net Framework project with packages.config nuget management format.

And contentFiles works for content files rather than lib folder. So you should not pack these dll files on target="lib\any\any\.....dll". You should pack them into contentFiles folder.

Use this:

<contentFiles>
      <files include="any/any/*" buildAction="Content" copyToOutput="true" flatten="true" />
 </contentFiles>

<files>
    <file src="xxx\First.dll(the physical, relative path of the dll on your project folder)" target="contentFiles\any\any\First.dll"></file>
   <file src="xxx\Second.dll(the physical, relative path of the dll on your project folder)" target="contentFiles\any\any\Second.dll"></file>
   <file src="xxx\....dll(the physical, relative path of the dll on your project folder)" target="contntFiles\any\any\.....dll"></file>

<files>

Then, you should install this nuget package on a Net Core project.

When you finish it, repack the project with nuget pack command, then, before you install the new one, clean the nuget caches first to remove the old previous version. Then, install the new version on a Net Core project and you can see the effect like this:

enter image description here

======================================================================

If you still want to have this function on a Net Framework project, you should pack these files on content node rather than contentFiles.

And you only need to add two lines:

        <contentFiles>
              <files include="any/any/*" buildAction="Content" copyToOutput="true" flatten="true" />
         </contentFiles>
        
        <files>
            <file src="xxx\First.dll(the physical, relative path of the dll on your project folder)" target="contentFiles\any\any\First.dll"></file>
           <file src="xxx\Second.dll(the physical, relative path of the dll on your project folder)" target="contentFiles\any\any\Second.dll"></file>
           <file src="xxx\....dll(the physical, relative path of the dll on your project folder)" target="contntFiles\any\any\.....dll"></file>
           
          <file src="xxx\First.dll(the physical, relative path of the dll on your project folder)" target="content"></file>
           <file src="xxx\Second.dll(the physical, relative path of the dll on your project folder)" target="content"></file>
    
   ..........

        <files>

But these simply cannot change the attributes of the imported file. And for net framework project, changing the property of the files cannot be done on xxx.nuspec file.

You should use <packages_id>.props or targets file.

1) create a file called <packages_id>.props under the build folder on the Solution Explorer, if your nuget package is named as ThisProject.1.0.0.nupkg, you should name it as ThisProject.props so that it will work.

This is mine:

enter image description here

2) add these on the props file:

<Project>
    <ItemGroup>
        <Content Include="First.dll">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </Content>
        <Content Include="Second.dll">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </Content>
        ......
            
    </ItemGroup>

</Project>

3) add a line on nuspec file to include the props file into the nupkg.

 <file src="build\xxx.props(the physical, relative path of the file on your project folder)" target="build"></file>

4) then repack the nuget package, clean the nuget caches, then install this new one on the Net Framework project with packages.config.

Note: although the Properties window of the imported content file on the solution explorer does not show the changed value and still shows the old one, the files are already copied into the output folder of the project. And it is an UI display issue on Solution Explorer and the changed values are already be used and work well. So you do not have to care much about that.