How to Exclude a T4 Template from a NuGet Package - nuget

I'm creating a NuGet package the provides a client for my WebAPI project by reflecting over the ApiControllers and creating classes for each one with methods that correspond to the actions defined on the controller. Unfortunately the .tt file is being included in the content folder when I run nuget.exe pack Client.csproj. I've tried creating a .nuspec file with a <files> directive, but I can't seem to exclude the file by itself. Does anyone know how to force the package to exclude the T4 template?
The project structure is roughly:
Website/
Controllers/
UserController.cs
...
Client/
Client.tt
Client.cs
namespace Client
class UserService
...
And I'd like a NuGet package like:
lib/
net45/
Client.dll
namespace Client
class UserService
But I'm getting something like this:
content/
Client.tt
lib/
net45/
Client.dll
namespace Client
class UserService
...

NuGet.exe Pack Client.csproj -Exclude **/*.tt

In my case the problem was inside csproj file, I had to fix
<Content Include="SomeFile.txt" />
to
<None Include="SomeFile.txt" />

Turns out the easy solution is to use the -Exclude option when creating the package via the command line.
NuGet.exe Pack Client.csproj -Exclude *.tt
The new package will look exactly as specified in the question.

If you are using Azure DevOps, I tried for a long time either trying using a custom nuget pack command with the -exclude, which did not work, or tried adding a .nuspec file and excluding the content from there. However, nothing worked.
How I fixed it in our project is clicking on each .tt file and setting the "Build Action" from "Content" to "None". It didn't seem to have an affect on the project in any way.
Maybe someone has a better solution, but I struggled with it for 1-2 days until I decided to screw it and just change the build action.

To build on #Baur's answer you can set this:
<None Include="SomeFile.tt" />
From the IDE, by right clicking the files and going to properties.
Click the BuildAction Property
Set it to None

Related

How to execute custom script when installing nuget package?

I created this project https://github.com/RemiBou/RemiBou.CosmosDB.Migration, for working it needs the user to do 2 things : create the appropriate folders and edit the csproj so the file inside those folders are embedded.
Before we could do that automaticly when installing with install.ps1 but this feature has been deprecated. Do you know any way how I could do this ?
install.ps1 isn't exactly deprecated, but it's a feature unique to packages.config. PackageReference has no concept of install as anyone can simply edit the csproj and add a PackageReference. When you restore, NuGet has no way of knowing if this is the first time the package is restored for the project after the reference was added, or if it's just the first time the project was restored with a clean repo (after a "msbuild /t:clean" or "git clone", for example).
I don't know an alternative for creating the folders other than having documentation that says the convention is to use that folder name. But, an alternative to modifying the csproj is to take advantage of the fact that MSBuild is a generic build system and NuGet packages can include MSBuild props and targets file.
In your specific case, I would create a props file that defines a property something like <RemiBouCosmosDBMigrationPath>CosmosDB\Migrations\</RemiBouCosmosDBMigrationPath>, which allows your package users to change the property to a different path be overwriting the property value in their csproj, if they prefer.
Then create a targets file which contains a target something like
<Target name="RemiBouCosmosDBMigrationsEmbedMigrations" BeforeTargets="???">
<ItemGroup>
<EmbeddedResource Include="$(RemiBouCosmosDBMigrationPath)**\*.js" />
</ItemGroup>
</Target>
You'll need to figure out what the best target name to put in the BeforeTargets attribute, but I hope you understand the idea. A csproj file is nothing more than a MSBuild file with certain conventions. MSBuild files can import other MSBuild files, and MSBuild and NuGet work together to allow MSBuild to import MSBuild files that come from restored packages. Just compose the MSBuild properties and items in a different way, and the end result can still be the same.

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).

Nesting files in Nuget package without PowerShell

The title says it all. I have files that I want to nest during the installation of a NuGet package but can't use PowerShell scripts since they won't be run any longer (see here).
Are there any other ways to achieve this goal?
UPDATE: By nested I mean like *.resx and *.Designer.cs or *.xaml and code-behind files *.xaml.cs. I know I can achieve that by adding a <DependentUpon> element in the *.csproj file but I don't know how I can add that element without using PowerShell.
UPDATE2: init.ps1 runs the first time a package is installed in a solution. That won't cut it though. I would need the script to run when the package is installed into a project just like install.ps1 was run up to NuGet3.
UPDATE3: What I want to do is to add 3 files into the Properties folder of the target projects (Resources.resx, Resources.tt and Resources.Designer.cs). They are a replacement for the usual resources implementation. These files are installed by the nuget package when it is added to the project.
This is the part of the *.nuspec file that adds them to the Content folder of the package. As only one of them is actually content (the others being an Embedded Resource and Compile respectively) it would be nice to be able to set their build actions accordingly but one step at a time.
<files>
<file src="Properties\Resources.resx" target="content\Properties\Resources.resx" />
<file src="Properties\Resources.tt.pp" target="content\Properties\Resources.tt.pp" />
<file src="Properties\Resources.Designer.cs" target="content\Properties\Resources.Designer.cs" />
</files>
As these files are added to the projects I want the nesting inside the *.csproj file and not happen via a separate *.props file if that is somehow possible.
Packages can add MSBuild items like this to a project by using a .props file in the package. It would contain the same content that you would put into the .csproj file.
The down side of this is that the content cannot be modified by the user. If you need to modify the user's actual project file and copy content to the project folder you would have to include a .targets file in your package and set BeforeTargets="Build" on your target. This would give you a chance to run before build and make changes as needed.
The build folder works for both packages.config and PackageReference (NETCore SDK) projects. You can find more out about it here: https://learn.microsoft.com/en-us/nuget/create-packages/creating-a-package#including-msbuild-props-and-targets-in-a-package

Automated injection of props/targets files not working for native C++ project

I am using automatic package restore in NuGet v2.8.50506.491 with Visual Studio 2013.
I have added a build folder to my package with a {package ID}.props file. However, the file is apparently not being injected into the vcxproj at restore time. The package and all its content are being restored correctly but none of the definitions are visible in vcxproj properties. This may be expected if property injection occurs in memory, but the build fails due to paths that are clearly defined in the props not having been inherited.
If I add an explicit reference to the props file in my local packages repository, the project builds successfully, therefore there is no issue with the paths in props file.
I have also tried adding the props within a "native" subfolder under build, also to no avail.
An extract from the nuspec:
<file src="build\MyPackage.targets" target="build\MyPackage.targets" />
I have also tried a targets file instead of/as well as a props file, but this does not work either.
I should add that I have defined Nuget.config in the sln folder, with an absolute path to my packages repository:
<config>
<add key="repositoryPath" value="C:\Packages" />
</config>
I was having this problem today, and eventually I realized that the names of my .nuspec and .targets files were different than the id of my package, which is apparently a problem. Renaming the .nuspec and .targets files to match the package id made NuGet start injecting into the vcxproj correctly. I'm not sure which of the two files was the problem, or if it was both, but it's working correctly now that all three names match.
Injection of .targets and .props file references happens only at the time when you install the NuGet package. This is the same as with .NET projects where assembly references are created only at package install time.
Later when you build the project the package restore mechanism merely downloads and extracts the NuGet package so that the previously "dangling" .target / .props / assembly references become valid references.

using Init.ps1 to add item in the csproj file

i am using Nuget to install a package due to some restrictions i have to generate a reference and the path of the assembly in my csproj file.
i am think of doing it with Init.ps1 file which runs when you first install the package.
the element that i want to add is the Reference element some thing like.
and should be like
<Reference Include="Library.MyLib.Imaging, Version=255.255.255.255, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\SDK.0.9.2\lib\wp8\X86\Library.mylib.Imaging.winmd</HintPath>
</Reference>
Can some body guide me that how i can add these to the csproj file. i belive that AddItem method can be used from the Project Class
project Class Reference
thanks
Be careful with the false assumption you made for init.ps1: that PowerShell script is run everytime the package is initialized (or every time the solution is loaded) which is likely not what you want in this scenario. You'll have to use install.ps1 instead, which is run once during installation of the package only.
The main issue with making changes to a consuming project file is that you'll have to know the file name somehow. The parameters that get injected into the PowerShell scripts are the following ones:
param($installPath, $toolsPath, $package, $project)
I've had a similar requirement and what I did instead of automating it during package installation: I expose a cmdlet in the Package Manager Console for the consumer to use.
You can find an example of my implementation on GitHub for the NuSpec package: https://github.com/myget/NuGetPackages/blob/master/NuSpec/tools/NuSpec.psm1
Maybe that will help you to get started. If you do have a proper solution to fully automate this during package installation, please feel free to share it here as well (or send me a Pull Request :-)).