10

I am trying to create a .NET standard nuget package of content files (with no managed assemblies), to be consumed by .NET Framework assemblies. My aim is to get this folder of files copied to the bin folder of the consuming assembly.

This question is similar Add native files from NuGet package to project output directory (and uses this nuget package http://www.nuget.org/packages/Baseclass.Contrib.Nuget.Output/), but I require my nuget package to be .NET Standard

I have added the files in the assembly under contentfiles\any\any\myfiles and added the following to the metadata section of the nuspec file:

<contentFiles>
    <files include="any/any/myfiles/*" buildAction="None" copyToOutput="true" />
</contentFiles>

When I try to add this to a .NET framework assembly I get the error

Could not install package 'myPackage 1.0.0'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.6.2', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.

I have also tried adding the files to the root of the project and adding the following beneath the metadata element in the nuspec file:

<files>
    <file src="myfiles\**\*" target="myfiles" />
</files>

Full nuspec file:

<?xml version="1.0"?>
<package>
    <metadata>
        <id>myPackage</id>
        <version>1.0.0</version>
        <title>myPackage</title>
        <requireLicenseAcceptance>false</requireLicenseAcceptance>
        <description>my files/description>
        <releaseNotes></releaseNotes>
        <tags></tags>
        <contentFiles>
            <files include="any/any/myfiles/*" buildAction="None" copyToOutput="true" />
        </contentFiles>
    </metadata>
    <files>
        <file src="myfiles\**\*" target="myfiles" />
    </files>
</package>

Also, in the csproj I've also changed the TargetFramework element to:

<TargetFrameworks>netstandard1.3;netstandard2.0;net40;net45;net46</TargetFrameworks>

SOLUTION:

In the end, this is the solution: "myFiles" is a folder that sits in the project root and contains many different files and sub-directories.

nuspec file:

<?xml version="1.0"?>
<package >
    <metadata>
        <id>myPackage</id>
        <version>1.0.0</version>
        <title>My Package</title>
        <tags></tags>
        <dependencies>
            <group targetFramework=".NETStandard2.0" />
            <group targetFramework=".NETFramework4.6.2" />
        </dependencies>
        <contentFiles>
            <!-- this sets "CopyIfNewer" on all files in the project that references this package -->
            <files include="**/*" buildAction="None" copyToOutput="true"/>
        </contentFiles>
    </metadata>
    <files>
        <file src="myFiles\**\*" target="contentFiles\any\any\myFiles"/>
    </files>
</package>

The project that references the nuget package will appear to have a folder called "myfiles" (with a link icon over all the files) which will get copied to the bin folder on build.

Brian Reichle
  • 2,798
  • 2
  • 30
  • 34
SturmUndDrang
  • 1,876
  • 5
  • 27
  • 47
  • I'm initially thinking the Build Action ought be something like "Embedded Resource" or "Content", not "none". I'm going off the options available in visual studio. Perhaps its better done as a "Resource1.resx" file, and link in the files to that? – Dan Rayson Aug 31 '18 at 07:48
  • no. @DanRayson it doesn't work that way. these types of projects effective build multible dlls by target framework. Rather, the issue that is presented here is in regards to project not targeting`net462` – Brett Caswell Aug 31 '18 at 08:04
  • also, in the csproj I've also changed the TargetFramework to TargetFrameworks "netstandard1.3;netstandard2.0;net40;net45;net46" – SturmUndDrang Aug 31 '18 at 09:11
  • it needs to be `net462` – Brett Caswell Aug 31 '18 at 09:13

1 Answers1

3

There are some inferred ways to do this, but add can add the targetFramework as setting of dependencies here.

<dependencies>
  <group targetFramework=".NETStandard1.3" />
  <group targetFramework=".NETStandard2.0" />
  <group targetFramework=".NETFramework4.0" />
  <group targetFramework=".NETFramework4.5" />
  <group targetFramework=".NETFramework4.6" />
  <group targetFramework=".NETFramework4.6.2" />
</dependencies>

I would also recommend separating the .dll files explicitly from your content files in the files section of the nuspec file, and reference the lib\<targetName>\ convention.. (which actually relates to the inferred sentiment I reference to above, but I don't have much detail to provide on that at the moment)

So your nuspec file would look like this:

<?xml version="1.0"?>
<package>
<metadata>
    <id>myPackage</id>
    <version>1.0.0</version>
    <title>myPackage</title>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>my files/description>
    <releaseNotes></releaseNotes>
    <tags></tags>
    <contentFiles>
       <files include="any/netstandard1.3/myfiles/*" buildAction="None" copyToOutput="true" />
       <files include="any/netstandard2.0/myfiles/*" buildAction="None" copyToOutput="true" />
       <files include="any/net40/myfiles/*" buildAction="None" copyToOutput="true" />
       <files include="any/net45/myfiles/*" buildAction="None" copyToOutput="true" />
       <files include="any/net46/myfiles/*" buildAction="None" copyToOutput="true" />           
       <files include="any/net462/myfiles/*" buildAction="None" copyToOutput="true" />
    </contentFiles>
    <dependencies>
        <group targetFramework=".NETStandard1.3" />
        <group targetFramework=".NETStandard2.0" />
        <group targetFramework=".NETFramework4.0" />
        <group targetFramework=".NETFramework4.5" />
        <group targetFramework=".NETFramework4.6" />
        <group targetFramework=".NETFramework4.6.2" />
    </dependencies>
</metadata>
<files>
   <file src="<your-path>\<yourprojectassembly.dll>" target="lib\netstandard1.3\<yourprojectassembly.dll>" />
   <file src="<your-path>\<yourprojectassembly.dll>" target="lib\netstandard2.0\<yourprojectassembly.dll>" />
   <file src="<your-path>\<yourprojectassembly.dll>" target="lib\net40\<yourprojectassembly.dll>" />
   <file src="<your-path>\<yourprojectassembly.dll>" target="lib\net45\<yourprojectassembly.dll>" />
   <file src="<your-path>\<yourprojectassembly.dll>" target="lib\net46\<yourprojectassembly.dll>" />
   <file src="<your-path>\<yourprojectassembly.dll>" target="lib\net462\<yourprojectassembly.dll>" />
   <file src="<your-path>\myfiles\*" target="content\myfiles" />
   <file src="<your-path>\myfiles\*" target="contentFiles\any\netstandard1.3\myfiles" />
   <file src="<your-path>\myfiles\*" target="contentFiles\any\netstandard2.0\myfiles" />
   <file src="<your-path>\myfiles\*" target="contentFiles\any\net40\myfiles" />
   <file src="<your-path>\myfiles\*" target="contentFiles\any\net45\myfiles" />
   <file src="<your-path>\myfiles\*" target="contentFiles\any\net46\myfiles" />
   <file src="<your-path>\myfiles\*" target="contentFiles\any\net462\myfiles" />
</files>
</package>

Screenshot of what that will look like from a project that references your nuget package. (my content was a text file, and target was "lib\<target>\any" respectfully)

enter image description here


It is worth noting that there may be some behavior considerations to the content in the assembly that references to your package though.

enter image description here

in the above image, the content that came from the nuget package is by default referenced as No Copy to Output and C# Compile as the BuildAction.

Brett Caswell
  • 1,486
  • 1
  • 13
  • 25
  • not that my screenshots do not reflect the code sample (which is based on questions sample); also, in my csproj, I do have BuildAction as 'Content' for my content files, and that is reflected in the nuspec file, but that is really more of a build consideration I think – Brett Caswell Aug 31 '18 at 09:48
  • So adding the dependencies in the nuspec fixed the error when adding to a .NET framework project. I can get the files included in the package under "myfiles" but they are not included in the build output directory – SturmUndDrang Aug 31 '18 at 12:01
  • @SturmUndDrang I had performed an edit or two after you said you'll try this, can you confirm you used `target="content\myfiles"` and `target="contentFiles\any\net462\myfiles"`, if so.. try changing `buildAction` to `Content` and remove `copyToOutput="true"`. then pack, push, and update nuget package references. – Brett Caswell Aug 31 '18 at 17:31
  • @SturmUndDrang wait.. "but they are not included in the build output directory" .. you mean after you do a build on the project that is referencing to your packages? I think that would relate to the "behavior consideration" I mentioned above. Build Action there should be changed to "Content".. at this point.. I don't know how to, or if you can, dictate that behavior in a package, and it seems somewhat out of the scope of the question and issue. Should be a separate SO question perhaps. – Brett Caswell Aug 31 '18 at 17:39
  • Yes - I want to include the files in the output folder of the project that is referencing my package. I can't set the Build Action in that project because there are no files in the project on which to do that. I could add a post-build step to copy the files from packages\myPackage\etc, but that doesn't seem like a very clean solution (but I will do this if this is the only way I can get the files copied across) – SturmUndDrang Sep 03 '18 at 07:03
  • To be clear; I don't get the files showing (as in your first screenshot) in a .NET 462 project but I do in a .NET standard 2.0 project – SturmUndDrang Sep 03 '18 at 07:55