I have a large EXE that my project needs, but I don't want to commit large EXEs into Git. So, seems to me a viable option is to pull it in through NuGet. Easy enough, I created a .nuspec file with my one EXE in it:
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Traefik</id>
<version>1.5.1</version>
<authors>Containous</authors>
<owners>MikeC</owners>
<projectUrl>https://github.com/containous/traefik</projectUrl>
<license type="expression">MIT</license>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Traefik binaries</description>
<copyright>Copyright ©2020 Containous</copyright>
</metadata>
<files>
<file src="traefik.exe" target="lib" />
</files>
</package>
I then run nuget pack
and create a .nupkg
file. Everything is correct:
However, when I try to reference my NuGet package in my project, I get the following error right when clicking the "Install" button:
Severity Code Description Project File Line Suppression State
Error Could not install package 'Traefik 1.5.1'. You are trying to install this package into a project that targets 'Unsupported,Version=v0.0', 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.
This is a NuGet package that has no assemblies and nothing to reference. It's simply content I want to pull in and copy somewhere using a post build action. Is it possible to create a NuGet package that has no assemblies to reference and is purely content (in this case, a single EXE file)? If so, what's the correct way to lay this out in the file structure? I've tried putting the EXE in a few places, such as "bin", "tools", "content", etc. Same error no matter what. Thanks!
The lib
folder is not suitable for this, because it is used for assemblies that your project references when installing the package. Apart from that, the folder structure must contain a suitable target framework folder like net472
. You cannot place assemblies directly unter lib
.
<file src="traefik.exe" target="lib/net472"/>
If you want to treat your executable as a pure content file, you can use contentFiles
.
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Traefik</id>
<version>1.5.1</version>
<authors>Containous</authors>
<owners>MikeC</owners>
<projectUrl>https://github.com/containous/traefik</projectUrl>
<license type="expression">MIT</license>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Traefik binaries</description>
<copyright>Copyright ©2020 Containous</copyright>
<contentFiles>
<files include="any/any/traefik.exe" buildAction="None" copyToOutput="true"/>
</contentFiles>
</metadata>
<files>
<file src="traefik.exe" target="contentFiles/any/any/traefik.exe"/>
<file src="traefik.exe" target="content/traefik.exe"/>
</files>
</package>
This way, the traefik.exe
will be copied directly to your output folder. Inside of your package, the folder structure will be like this. This folder structure is predefined for content files.
content
- traefik.exe
contentFiles
- any
- any
- traefik.exe
You can even target a distinct or multiple frameworks with this approach. Say you have a special executable for .NET Framework 4.7.2, then adapt the second any
to your target framework moniker, here net472
. The executable will then only be copied to your output folder if the framework matches your project framework.
<files include="any/net472/traefik.exe" buildAction="None" copyToOutput="true" flatten="true"/>
<file src="traefik.exe" target="contentFiles/any/net472/traefik.exe"/>
Of course, you can define multiple executables for different frameworks like this. A few remarks about the NuSpec file. The executable is also copied to the content
folder of your package for backwards compatibility, because contentFiles
is supported only since NuGet 4.0 using PackageReference
.