1

I have the following declared in my csproj.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Content Include="TextFile1.txt" Link="Files\TextFile1.txt">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    <Content Include="Files\TextFile2.txt">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>

</Project>

Upon building the application I am getting the following bin/debug structure enter image description here enter image description here

As you can see both files are in the subdirectory Files, and no text file is in the root folder, since the file in the root folder isn't marked as <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> but the link is.

Now I want to pack this application, which fails to respect my linking of the file and dumps the TextFile1.txt into the root folder.

The created *.nuspec file looks like this

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
  <metadata>
    <id>ConsoleApp44</id>
    <version>1.0.0</version>
    <authors>ConsoleApp44</authors>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Package Description</description>
    <dependencies>
      <group targetFramework="net5.0" />
    </dependencies>
    <contentFiles>
      <files include="any/net5.0/TextFile1.txt" buildAction="Content" />
      <files include="any/net5.0/Files/TextFile2.txt" buildAction="Content" />
    </contentFiles>
  </metadata>
</package>
Sara Liu - MSFT
  • 6,007
  • 1
  • 21
  • 27
Rand Random
  • 7,300
  • 10
  • 40
  • 88

1 Answers1

2

If you just want the TextFile1.txt and TextFile2.txt from the nuget package to be copied into the same folder structure into the main project's output folder, you could try this:

Two tips:

  1. to make files from nupkg be copied into the main project's output folder, you should use <PackageCopyToOutput>true</PackageCopyToOutput>.

  2. use the PackagePath to specify the folder structure

Use this part under ConsoleApp44.csproj file:

<ItemGroup>
        <Content Include="TextFile1.txt">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
            <Link>Files\TextFile1.txt</Link>
            <PackagePath>content\Files;contentFiles\any\any\Files</PackagePath>
            <PackageCopyToOutput>true</PackageCopyToOutput>
        </Content>
        <Content Include="TextFile2.txt">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
            <Link>Files\TextFile2.txt</Link>
            <PackagePath>content\Files;contentFiles\any\any\Files</PackagePath>
            <PackageCopyToOutput>true</PackageCopyToOutput>
        </Content>
    </ItemGroup>

Actually, the PackagePath is to specify the custom output folder structure into the main project when you install the nuget package. You can change the structure according to your needs.

Then, you should re-pack the lib project, uninstall the old version of the nuget package, clean nuget caches or just delete all files under C:\Users\xxx\.nuget\packages. After that, reinstall the new release version.

Sara Liu - MSFT
  • 6,007
  • 1
  • 21
  • 27
  • Thanks a lot. Only noticed after @Andy's answer, that the files didn't output when I used the nuget package, so I actually had two issues the files didn't output and the folder structure wasn't how I liked it. So, what I read from your answer both issues got tackled and I don't have to alter the *.nuspec file manually, will try it tomorrow and report back, but seems promosing. Do you know where I can find documentation of `PackageCopyToOutput` and the likes, isn't the first time I wanted to alter my nuget package and failed to do so, and fought the only way is to manually edit the nuspec file? – Rand Random Apr 13 '21 at 08:16
  • Since now, you could directly modify the csproj only for new-sdk project to pack nuget package without writing an additional nuspec file. My answer quite has a bit problem. Now you donot have to worry about it, I have updated my answer. Hope any feedback tomorrow! – Sara Liu - MSFT Apr 13 '21 at 08:37
  • 1
    [Check this document](https://learn.microsoft.com/en-us/nuget/reference/msbuild-targets#including-content-in-a-package). – Sara Liu - MSFT Apr 13 '21 at 08:43
  • 1
    This is awesome -- I never knew about `` That adds the `copyToOutput="true"` attribute that was in my answer automatically. That's been driving me nuts for years. – Andy Apr 13 '21 at 13:57
  • @Andy, Sorry for that. I intended to contact the owner. And be glad to know that it does help for you:) – Sara Liu - MSFT Apr 15 '21 at 02:19
  • @RandRandom, any update about it? Does it work during your test? – Sara Liu - MSFT Apr 15 '21 at 02:19
  • Sorry, that I failed to keep my promise. – Rand Random Apr 15 '21 at 05:29
  • Just checked and seems to work as expected. – Rand Random Apr 15 '21 at 05:34
  • I have one little question though, maybe you know what I am doing wrong. My `csproj` is declared as a multi-target project eg. `netframework4.7;net5.0` instead of `any\any` - why two any in the first place? - I tried to declare it like this `content\Files;contentFiles\any\$(TargetFramework)\Files` – Rand Random Apr 15 '21 at 05:35
  • (cont) ... but `$(TargetFramework)` seems to be empty and it resulted in a package with where the files are stored in this path `ConsoleApp44.1.0.0\contentFiles\any` it seems like it wants a subdirectory for the targetframewok or any, but I can't seem to specify the target framework. So the double `any\any` produce this, `ConsoleApp44.1.0.0\contentFiles\any\any\Files` would like to have two seperate folders for the targetframework eg. `ConsoleApp44.1.0.0\contentFiles\any\net5.0\Files` – Rand Random Apr 15 '21 at 05:35
  • Tough, it isn't necessary for my use case, it is just me being picky, everything seems to work fine with `any\any` in place. – Rand Random Apr 15 '21 at 05:38
  • 1
    Just see [this document](https://learn.microsoft.com/en-us/nuget/reference/nuspec#package-folder-structure). It is the feature of contentFiles node. And it should be the structure like `/contentFiles/{codeLanguage}/{TxM}/{any?}`. The first `any` is the file type: like `cs`,`vb`, `any` is generic, it means it could deal with all the types. The second `any` is the targetframework, `any` means that all the targetframework could install the below content files. So use `any\any` is the easiest way. Also, you cannot use `targetframework` under pack process with multiple targetframeworks. – Sara Liu - MSFT Apr 15 '21 at 07:03
  • 1
    I find it is an issue and you should report to [the team](https://developercommunity.visualstudio.com/search?space=8). It is always empty under that during the extra pack process. To avoid that, use `any\any`. Or you should specify them one by one. Use `any\net47` and `any\net5.0`. Most similar issue like [this similar issue](https://stackoverflow.com/questions/65915099/creating-a-nuget-package-with-exe-file-as-content-file/65933251#65933251). You should avoid using `targetframework` under multiple targetframeworks during pack process. – Sara Liu - MSFT Apr 15 '21 at 07:05