Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tell nuget to add package resource files as links, and not copy them into project directory

Tags:

c#

.net

nuget

Intro (how to pack resources into a nuget package)

To pack some resource files into a nuget package, what one would normally do, is the following.

Put all the resource files into the content\ directory of a nuget package. This would be specified by the following line in a .nuspec file:

<files>
  <file src="Project\bin\Release\script.js" target="content\js\script.js" />
<files>

Now, when this nuget package gets installed into AnotherProject, the following file structure emerges:

Solution.sln
packages\Project.1.0.0\content\js\script.js  // the original resource file
AnotherProject\js\script.js                  // a physical copy 
AnotherProject\AnotherProject.csproj         // <Content /> tag (see below)

During package installation, AnotherProject.csproj was injected with tag:

<Content Include="js\script.js" />

and this is for the physical copy of the original resource (which is under packages\ directory).

The actual problem (how to pack resources into a nuget package as link)

My aim is not to have the physical copy of a resource file in the AnotherProject directory but rather a "link" to the original resource under packages\ directory. In the csproj, this should look like this:

<Content Include="packages\Project.1.0.0\content\js\script.js">
  <Link>js\script.js</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

Brute force solution that I would rather avoid

Now, one "do it the hard way" workaround I can think of is:

  • not putting resource files under content\ so they do not get added automatically,
  • writing Install.ps1 script that would hack the csproj file structure and add the necessary XML piece manually,

This, however, has the following drawbacks:

  • all my nuget packages need the same script piece in their Install.ps1,
  • when installing my packages, there would be a nasty "project reload prompt" in Visual Studio.
like image 521
jaccus Avatar asked Aug 18 '14 16:08

jaccus


1 Answers

Since NuGet currently does not support this out of the box your options are either to use PowerShell or to use a custom MSBuild target.

PowerShell

  • Leave your resources outside of the Content directory in your NuGet package (as you already suggested).
  • Add the file link using PowerShell in the install.ps1.

You should be able to avoid the project reload prompt if you use the Visual Studio object model (EnvDTE). I would take a look at Project.ProjectItems.AddFromFile(...) to see if that works for you.

MSBuild target

  • NuGet supports adding an import statement into a project that points to an MSBuild .props and/or .targets file. So you could put your resources into the tools directory of your NuGet package and reference them from a custom MSBuild .props/.targets file.

Typically the custom .props and .targets are used to customise the build process. However they are just MSBuild project files so you could add items for your resources into these project files.

Note that .props are imported at the start of the project file when a NuGet package is installed, whilst .targets are imported at the end of the project.

Customising NuGet

Another option, which would take more work, would be to modify NuGet to support what you want to do.

like image 191
Matt Ward Avatar answered Oct 29 '22 21:10

Matt Ward