Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I include a text file alongside my class library in my NuGet package which Visual Studio 2017 is creating for me?

My text file is in my class library project. I have its Build Action set to Content and Copy to Output Directory set to Copy if newer, so the .csproj has a section like:

<ItemGroup>
  <Content Include="MyFile.txt">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
</ItemGroup>

I'm doing this because I need to use the text file from my class library, and can't have it as an embedded resource because I want to allow end-users to edit it. When I use VS 2017 to create the package it gives me a .nuspec with a section like this:

<contentFiles>
  <files include="any/net46/MyFile.txt" buildAction="Content" />
  <files include="any/netstandard1.3/MyFile.txt" buildAction="Content" />
</contentFiles>

Then when I reference the package from another project, MyFile.txt appears at the root of the project with Build Action set to Content but Copy to Output Directory set to Do not copy. I just want the file to be included alongside the .dll, without being included in the referencing project.

like image 433
user1676558 Avatar asked Mar 17 '17 06:03

user1676558


2 Answers

The following will create a nuget package that persists your chosen file(s) alongside your package's dll when a consuming application installs it and can be done entirely through the Visual Studio 2017 IDE.

Let's pretend you have a C# project called Foo.Bar in your solution that you would like to build into a nuget package:

In Visual Studio, right-click the project Foo.Bar > Properties and go to the Package tab. Make sure the value for Package id: is Foo.Bar.

Create a Foo.Bar.targets file in the same directory as your Foo.Bar.csproj file with the following content:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <None Include="$(MSBuildThisFileDirectory)\MyFile.txt">
      <Link>MyFile.txt</Link>
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>

Right click the project in Visual Studio 2017, and select Edit Foo.Bar.csproj. Put the following block in the opened project file:

<ItemGroup>
    <None Include="MyFile.txt">
      <Pack>true</Pack>
      <PackagePath>build</PackagePath>
    </None>
    <None Include="Foo.Bar.targets">
      <Pack>true</Pack>
      <PackagePath>build</PackagePath>
    </None>
  </ItemGroup>

Now when you right click the project and select Pack (or if you run dotnet pack from the command line in the directory where your project resides), it will generate a .nupkg file for your Foo.Bar project. MyFile.txt and Foo.Bar.targets will be in the build folder inside of it.

As a test I installed it into a sample Console App project. After doing so, MyFile.txt is present in the Solution Explorer of the Console App and can be opened and edited. Furthermore, if I publish the console app, both Foo.Bar.dll and MyFile.txt are in the bin > Release > [TargetFramework] > publish folder of the published files (if published using a Folder Profile to local disk).

An interesting thing to note is that at time of writing, if you right click MyFile.txt in the Console App that installed the package and select Properties, you'll see that Copy to Output Directory is set to Always. If I try to change it to Do Not Copy or anything else, it will revert back to Always when the dialog is closed despite clicking OK. It will act as if you click Cancel every time. This is because of the edit made to the original Foo.Bar.csproj file that produced the nuget package, specifically: <CopyToOutputDirectory>Always</CopyToOutputDirectory>.

like image 158
David Gunderson Avatar answered Oct 06 '22 11:10

David Gunderson


If you want to keep .nuspec, then you can edit it manually and add copyToOutput="true" attribute.

If you're using VS2017 and want to edit your .csproj, then you should be able to specify extra metadata in your .csproj file (and you can set custom build action if necessary):

<Content Include="MyFile.txt">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    <IncludeInPackage>true</IncludeInPackage>
    <BuildAction>Content</BuildAction>
    <CopyToOutput>true</CopyToOutput>
</Content>
like image 28
Igor Labutin Avatar answered Oct 06 '22 10:10

Igor Labutin