Is there an alternative to contentFiles with projects that use packages.config? - nuget

I have a nuget package with content that I want to be copied to the build output when users install my package. There is support for this: NuGet ContentFiles Demystified in NuGet v3.3. However, it only works in projects that use project.json. The contentFiles are not copied to my build output when I have a project that uses packages.config.
Is there an alternative or workaround I could use in order to make my NuGet package work on projects that use either a project.json or packages.config?

A quick search on StackOverflow reveals the following question which I think covers what you are asking for:
Set content files to "copy local : always" in a nuget package
You can put your files inside a Content directory inside the NuGet package.
In your .nuspec file:
<file src="css\mobile\*.css" target="content\css\mobile" />
When you install that into your project it will add the css\mobile directory to your project and the files inside that directory.
However that only adds the files to the project. In order to get them to be copied to your output directory you would either need to use a PowerShell script to modify the project item's copy local information.
An alternative, possibly a better way, would be to use a custom MSBuild .targets file. This will be added as an import to your project and then inside your .targets file you can add the files you want and specify the copy to output information directly as though it was part of your project. NuGet .nupkg file content:
\build
\Net45
\MyPackage.targets
\Foo.txt
MyPackage is the id of the NuGet package above.
Inside the .targets file you specify the files (e.g. Foo.txt).
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="Foo.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

Related

Output Directory of native dll bundled with NuGet

I am trying to build a NuGet package that includes native DLLs which are to be placed in the output folder when a project uses the package. I have tried to use the several suggestions from this question, but I am always running in the same problem.
My current NuGet package layout is like this:
\build
packageId.targets
file1.dll
file2.dll
\lib
\netstandard1.4
assembly.dll
The contents of packageId.targets is:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<NativeLibs Include="$(MSBuildThisFileDirectory)\*.dll"/>
<None Include="#(NativeLibs)" Link="$(RecursiveDir)$(Filename)$(Extension)">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
This should, according to the answers of the other questions, lead to my DLLs being placed in the bin\Debug directory of the project using the package. However, they are not. Instead, they are placed in bin\Debug\packages\packageId\build.
Now I have experimented a lot, and I noticed more and more strange behavior which I cannot make any sense of:
If I move the DLLs to the root of the NuGet package (like one answer suggests) and change the .targets file accordingly, they are not copied at all. There also is no error message.
If I change the .targets file to only reference file1.dll in both Include= and Link=, both files get copied anyway.
So I wondered if some policy just ignores the .targets file and copies whatever is in build to that path in the output folder, but when I remove the .targets file, the DLL files will not get copied anymore.
Now I understand even less what's happening.
What do I need to change to get the DLLs copied right into bin\Debug?
The new way to handle runtime-specific assents in NuGet is to use the runtimes folder to place native assets:
\lib
\netstandard2.0
ManagedWrapper.dll
\runtimes
\win-x86
\native
NativeThing.dll
\win-x64
\native
NativeThing.dll
\linux-x64
\native
libNativeThing.so
\osx-x64
\native
libNativeThing.dylib
If the package is consumed from a .NET Framework project, you may need to add a reference to the Microsoft.NETCore.Platforms package wich provides the runtime graph (runtimes.json) for NuGet to provide proper RID mappings if you don't use base RIDs (e.g. win10-x64 falls back to win-x64 resources).

Nuget scripting in VS 2017

I want to add a custom install script for my VS 2017 NuGet package.
Problem is, support for the install.ps1/uninstall.ps1 mechanism was removed. init.ps1 still works, but it would run every time the solution is opened, and that is unacceptable (it's a potentially lengthy process).
I read it's possible to define custom msbuild targets in the build dir, but I cannot get that to work because it requires manipulating the .nuspec file to include the files, and I can't see how to do that in VS 2017 with just the .csproj file.
but I cannot get that to work because it requires manipulating the .nuspec file to include the files
You can use the NuGet Package Explorer to add custom msbuild .targets in the build directory without manipulating the .nuspec file:
I can't see how to do that in VS 2017 with just the .csproj file.
As you know, Powershell script support was modified to no longer execute install and uninstall scripts, so we could not custom install scripts that is called when installing the nuget package, otherwise, we need to overwrite the NuGet API in visual Studio: IVsPackageInstaller interface(Not recommended).
So as a workaround, we could use define custom msbuild .targets file to achieve what you want achieve by the custom install script after install the nuget package. For example, you want custom install nuget script to change the default dll output, you can use a .target file with copy task to achieve it, you can create a file build\MyNuGet.targets containing:
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<MySourceFiles Include="$(ProjectDir)MyFolder\**" />
</ItemGroup>
<Target Name="MyNuGetCustomTarget" AfterTargets="Build">
<Copy SourceFiles="#(MySourceFiles)" DestinationFolder="$(OutDir)" />
</Target>
</Project>

How to prevent nuspec token replacement on package install

I have a nuspec template file (template.nuspec.pp) in the content folder of a Nuget package. When the package is installed, I modify the name of the nuspec file using an install.ps1 script to match the targeted assembly. I want the contents of the nuspec file to remain unchanged:
<?xml version="1.0"?>
<package>
<metadata>
<id>$rootnamespace$</id>
<version>$version$</version>
<title>$rootnamespace$</title>
<authors>$author$</authors>
<!--<iconUrl></iconUrl>-->
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$rootnamespace$</description>
<copyright>$copyright$</copyright>
<tags></tags>
</metadata>
</package>
The replacement tokens are replaced immediately on installation, however - I was under the impression this should happen only when nuget pack is called. Why is this happening, and what need I do to prevent it?
In case folks wonder, my install.ps1 file is not touching the contents of the nuspec template.
Looks like the whole point of the .pp suffix is to denote that any variable enclosed by $ is replaced on package install. When I removed the .pp suffix, the files were then ignored by Nuget and not added to the content folder. In order to circumvent this, I had to add a non .pp suffix to the file (I used .txt) and then renamed it using an install.ps1 script in my tools folder.

which is good approach to create nuget packages?

As I developer I wonder which is the best approch to create a nuget packages ?
1.NuGet Package Project (link)
2.Use Nuget.exe use .Nuspec (add manually and update manually)
Anyone guide on this.
Currently I'm using nuget.exe and .Nuspec but problem is everytime I have to manually update .nuspec if any new project is added.
Is there any other good options to do so ?
You can also build a NuGet package by running the nuget pack command against the csproj file. More information can be found here: Creating And Publishing A Package
Create nuget package in the following manner
Download nuget.exe from here https://www.nuget.org/
Create empty spec file (execute below command under project root folder)
nuget spec
Update nuget spec file SomeLib.nuspec according to your library properties(use any text editor)
Create some folders nugetPack/lib/net46/ and then paste the dll here; which you want to make as nuget package
Create nuget package (execute below command under project root folder)
nuget pack -basepath nugetPack SomeLib.nuspec
Now use this nuget package in your project
Set the nuget package source which you have created
Goto Visual Studio > Tool > NuGet Package Manager > Package Sources > here add your nuget package source folder path
Right click and select managae nuget packages on the project where you want to consume nuget package.
Select the right package source from the top right drop down box.
search your nuget package and install.
Another cool way to create nuget package via NuGet Package Explorer
which you can download it from here https://npe.codeplex.com/ then just simply fill the form and save the nuspec file to your local nuget package source folder.
Sample nuspec file whihc has some dependencies
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>your.package.name</id>
<version>1.0.0</version>
<title>package title</title>
<authors>NG</authors>
<owners>NG</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>some description</description>
<summary>some summary</summary>
<copyright>open</copyright>
<language>en-US</language>
<tags>your package keyboards</tags>
<dependencies>
<dependency id="Microsoft.AspNet.WebApi.Core" version="5.2.3" />
<dependency id="Microsoft.AspNet.WebApi.Client" version="5.2.3" />
<dependency id="Newtonsoft.Json" version="9.0.1" />
</dependencies>
</metadata>
</package>
Github README
I'm new to developing nuget packages, (and posting on Stack Overflow). I started using the nuget.exe command-line approach, which I learned about: here. But from what I've gathered so far, there is a convention of using .NET Standard, instead of .NET Framework when developing nuget packages. Especially on nuget.org. So, when developing a .NET Standard class library, check out the project properties under the project tab in Visual Studio. There you will see multiple tabs on the left, starting with build. Click on the Package tab. Now you'll see a great way to enter all properties that you would normally have to do manually when trying to create the .nuspec file. You'll want to be sure to fill it out completely to avoid flags when uploading to nuget or wherever. Create your repository and file in github, and enter their URLs. Also, imgur.com is a great place to host your icon image. Be sure to click the Generate Nuget Package checkbox. Voila! Now build your library and you'll notice a .nupkg file. This is the best resource.

Install specific dlls from nuget package

I have a .sln package named MySolution. In that Package I have some dlls, like:
MySolution.sln
\one.dll
\second.dll
\another.dll
I want to install only specific dll to my another Project, so they will add as reference to my Project. I m trying to install like
PM> Install-Package MySolution
In that way all dlls added to my Project, but I only want some of dlls like one.dll and second.dll thats it.
Is there any way to do this?
Your options are:
Add the .dlls you do not want as assembly references as Content files.
<file src="lib\Net40\another.dll" target="content" />
This will add the .dll as a file to the project.
Add the .dlls you do not want as assembly references as Tools files.
<file src="lib\Net40\another.dll" target="tools" />
The tools directory is one of the sub directories where your package is extracted to.
Then use PowerShell to put the files into the location you need them in the project.
Or alternatively you could write a custom MSBuild target file which references the files from the tools directory. Your MSBuild target file is a just an MSBuild file where you can define properties and files just like a standard MSBuild project file. So you can reference the .dlls in the tools directory and have them copied to the output directory.