How to modify .nuspec file before NuGet pack in Visual Studio - visual-studio

Visual Studio makes creating NuGet packages easier these days by automating the process of creating the .nuspec file. It means that version dependencies etc. are automatically created and you can simply set up the textual values here:
So, most of the work is already done by the time the NuGet package is built. However, there are external assemblies that I need to add to the .nuspec file before it is built. I know I can add external files in the files collection of the outputted .nuspec file (in obj\Release):
My question is, what build event or otherwise should I use to edit the .nuspec after it is created, but before the pack command is called by msbuild or Visual Studio? Or, should I just run a separate build process afterwards?
Note: a bonus would be to find a tool which I can call that will add the files collection. Without that, I'm guessing I will need to write powershell code to add the files...

You could use Pack element in csproj file: https://learn.microsoft.com/en-us/nuget/reference/msbuild-targets#including-content-in-a-package
Add something like this to your project:
<ItemGroup>
<Content Pack="True"
PackagePath="lib\netcoreapp2.2"
Include="C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All\2.1.2\Microsoft.AI.DependencyCollector.dll" />
</ItemGroup>
This will add a Microsoft.AI.DependencyCollector.dll library to your package:
This way you can add whatever you like to your library.

Related

Is there a way to prevent visual studio to remove a file or write ItemGroup with remove action?

I'm working on a project where I generate C# classes in a pre-build step using XSLT and XML to generate those. Those generated classes are included in one file, let's name it "MyClasses.cs" file. The problem now is, if a developer removes the file from the solution after the build is done and try to build the solution again, I see ItemGroup added like that under the project file as follows:
<ItemGroup>
<Compile Remove="MyClasses.cs" />
</ItemGroup>
While this won't prevent the generation of the classes again, it causes the solution to not build because the generated classes won't be included in the project. Meaning, the file needs a developer to include manually (right click and include it) so the entire solution can build. So, I wanna do is prevent people to remove the generated code "MyClasses.cs" file so that they can always build or override the behavior of Visual Studio to add an ItemGroup with Remove action for that file when removing it. Is that possible?

How do you get NuGet package restore to work on locally deployed packages stored in VSIX targeting Visual Studio 2019?

I am aware there are multiple questions on this topic already, but they all seem outdated. To clarify, I am using the "new" VSIX manifest format, and trying to follow the official instructions here: https://learn.microsoft.com/en-us/nuget/visual-studio-extensibility/visual-studio-templates
I have one project template and a couple of item templates that go with it. They all depend on deploying a NuGet package that should come bundled locally with the VSIX. I have examined the resulting VSIX file and all the files seem to be in the right place:
The project template has the required XML for declaring which packages to install:
<WizardExtension>
<Assembly>NuGet.VisualStudio.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</Assembly>
<FullClassName>NuGet.VisualStudio.TemplateWizard</FullClassName>
</WizardExtension>
<WizardData>
<packages repository="extension" repositoryId="VsixID.etc.etc">
<package id="Rx-Linq" version="2.2.5" />
</packages>
</WizardData>
The repositoryID matches the ID attribute in the .vsixmanifest file.
There is an individual Asset entry for each package, with the form:
<Asset Type="Rx-Linq.2.2.5.nupkg" d:Source="File" Path="Packages\Rx-Linq.2.2.5.nupkg" d:VsixSubPath="Packages" />
I have removed all packages.config and all the package references from the .csproj file installed by the VSIX (and even from the VSIX project itself just for good measure).
I have inspected the output VSIX and there is indeed a Packages folder in the VSIX containing all the .nupkg files. This folder is indeed unpacked and copied into the Visual Studio Extensions folder.
Despite all this, when I create a new project with the template, VS displays an error message saying: Failed to restore package from C:\users\<pathtoextensions>\Packages.
The thing is, the .nupkg files are actually present in the exact folder that the error message refers to.
I have been searching this for days and I can't seem to find any reference to best practices that actually work. It seems like these VSIX manifests are geared towards the legacy packages.config way of doing things, and there are discussions about how to extend them to use PackageReference instead.
Can anyone give any advice at all at how we are supposed to proceed going forward? Are packages not supposed to be deployed with the VSIX anymore? Are we supposed to just fill in the project with PackageReference entries and just let the user resolve them manually?
I feel like I am missing something fundamental here and any insight would be extremely valuable.
Update: I have also opened an issue on the NuGet github repository, as this is clearly a problem with the PackageRestore feature when restoring packages stored in a VSIX installer. Everything else mentioned in this question is working as intended and expected, except the package restore.
How do you actually include NuGet packages in Visual Studio Project
Templates VSIX targeting Visual Studio 2019?
Actually, there is no way to specify in a VS project template project that nuget packages can be used both using packages.config and PackageReference. Only two project templates of nuget management types can be created separately.
I have an easy way and since you have some issues with PackageReference format, you can try this funtion:
PackageReference
1) add these reference node in projecttemplate.csporj file:
<ItemGroup>
<PackageReference Include="Rx-Linq">
<Version>2.2.5</Version>
</PackageReference>
</ItemGroup>
2) When you create a project by this project template, please check these two options and VS will automatically read xxx.csproj and then recover the corresponding nuget package based on the information in it during build process.
Note: also make sure that the nuget url is checked and can be access under Package Source.
packages.config
In additon, for packages.config, you can just create a file named packages.config and then add your nuget info into it:
1)
2) add these into projecttemplate.csproj file:
<ItemGroup>
<Content Include="packages.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Reference Include="Rx-Linq, Version=2.2.5, Culture=neutral, PublicKeyToken=eb42632606e9261f, processorArchitecture=MSIL">
<HintPath>..\packages\Rx-Linq.2.2.5\lib\net472\xxxxxxx.dll</HintPath>
</Reference>
</ItemGroup>
Note: if this nuget package has dependencies, you should also add them(above steps) into packages.config and xxxx.csproj file. This funcution is a little more complicated than yours but it works. So, I recommend that you use PackageReference format.
More info you can refer to this similar issue.

Building NuGet packages from Visual Studio

I'm trying to share an internal company assembly via NuGet packages and a private source. This assembly targets .NET Framework 4.6.1. I want these NuGet packages to pack automatically from Visual Studio during the release build. I see I can add <GeneratePackageOnBuild>true</GeneratePackageOnBuild> to .csproj. I'm not sure if this is a .NET Standard-specific property but it seems to partially work. However, when I build, I get
error MSB4044: The "GetPackOutputItemsTask" task was not given a value for the required parameter "PackageOutputPath".
I've been trying to learn how to pass this parameter from within Visual Studio but I don't see a lot of documentation on parameters except when calling it from the command line manually. Is there an easy way to do this from within Visual Studio? Am I going about this wrong?
Edit: This is using a .NET Framework class library. I can run the pack command from the command line giving it the required parameters with /p:PackageOutputPath="path\here". It seems this might have been designed for .NET Core and Standard projects and Visual Studio might not handle packing .NET Framework projects.
To enable on-build packing in a "non SDK" project, using old .NET framework (eg:. 4.5.1) and visual studio 2019 without using custom Target. you need to do the following step:
add a first PropertyGroup tag on the csproj
add minimal tags Authors and PackageOutputPath
check that the same PropertyGroup has GeneratePackageOnBuild
Now the variables will be passed to the internally triggered msbuild -t:Pack command.
Here an example of working configuration, please make sure this will be the first <PropertyGroup> of the .csproj:
<PropertyGroup>
<Title>packageid</Title>
<Description>your description</Description>
<Version>1.1.1</Version>
<ReleaseNotes>New package system</ReleaseNotes>
<Authors>authors</Authors>
<Owners>owners</Owners>
<Copyright>your copyrights</Copyright>
<PackageOutputPath>bin\Package</PackageOutputPath>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
If you are looking for the references, here:
how to create a nuget package with msbuild
all possible tags to set on the csproj on the first PropertyGroup
Am I going about this wrong?
This GeneratePackageOnBuild property is not something for .net framework projects. Create a new .net Standard or .net Core class library project, right-click the project you'll see a Pack command(not available for .net framework).
If we click the button, VS will pack that assembly into a nuget package. And if someone doesn't want to click that button every time manually, go Project=>Properties=>Package we can see the Generate Nuget Packages on build checkbox. Enable it, and then the nuget package will be created after every build.
Actually, enabling that checkbox in VS will add statement <GeneratePackageOnBuild>true</GeneratePackageOnBuild> to xx.csproj, but the Pack button or Package tab in Project=>Properties are not available for .net framework projects.
So I'm afraid the answer is negative, you should't use that property for .net framework projects.(I tested the property in VS2017 and VS2019, it all just did nothing, can't reproduce the partial work mentioned in your question)
Is there an easy way to do this from within Visual Studio?
You need to use nuget pack command to do that as Lex Li says. And to do this in VS automatically, you can consider configuring that command in Post-Build-Event or using custom after-build target to run that command.
Since you want these NuGet packages to pack automatically from Visual Studio during the release build. You can try adding this script into your xx.csproj file:
<Target Name="CustomPack" AfterTargets="build" Condition="'$(Configuration)'=='Release'">
<Message Text="Custom Pack command starts ..." Importance="high"/>
<Exec Command="nuget pack $(MSBuildProjectFile) -Properties Configuration=Release"/>
</Target>
To run this script successfully, you need to download the nuget.exe and add the path of it to Environment Variables. Or use the full path like "C:\SomePath\Nuget.exe" pack ...
If the build in release mode succeeds, you'll see a xx.nupkg file in project folder.
In addition:
1.For more details about nuget pack command please see this document.
2.And don't forget to create a xx.nuspec file in project folder to avoid encountering warnings like NU5115(xxx was not specified). Similar issue see here.
I have a unique situation of needing to Register for Com Interop for and older application but also needing to pack for use in other internal applications and development in our company. I actually got this to work for a .NET Framework project from Visual Studio. Manually adding GeneratePackageOnBuild did attempt to make a package for me in VS2017. I was also able to add other .NET Core project properties such as <Authors>,<Description>, etc. I haven't tried VS2019 yet so maybe that is more restricted but I hope not.
The issue is VS2017 doesn't feed the pack target the output parameter (in this type of project). So then I tried to call pack in the After Build events but that causes a recursive loop because packing also attempts to build (dotnet and nuget both seem to call the msbuild pack target which calls a build). I then found an option -p:NoBuild=true for msbuild that allows me to call the pack target without msbuild actually building the project. Therefore I added the following command to <PostBuildEvent> and it works.
"$(MSBuildBinPath)\msbuild" -t:Pack "$(ProjectPath)" -p:PackageOutputPath="$(SolutionDir)..\packages" -p:NoBuild=true
Edit: I eventually used the following in my csproj. Calling nuget directly worked better because I had a nuspec file that was not getting merged or fully used when calling MSBuild directly.
<Target Name="CustomPack" AfterTargets="Build" Condition="'$(Configuration)'=='Release'">
<Message Text="Custom Pack command starts ..." Importance="high" />
<Exec Command=""nuget" pack "$(ProjectPath)" -OutputDirectory "$(ProjectDir)..\..\packages" -Prop Configuration=Release" />
</Target>
Add this to your proj file to use the pack target on .net framework projects.
<PackageReference Include="NuGet.Build.Tasks.Pack" Version="6.4.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
if you want to run from command line then use this:
msbuild -t:restore

Visual Studio not creating nuget package on build

I have a class library targeting net471 and I have set up the information in Properties->Package. Generate nuget package on build is also checked.
I'm also trying to create package manually by right-clicking on the project and selecting Generate nuget package.
When I build the project, no package is created.
Am I missing something?
Note: I'm using the latest version of Visual Studio Community 2017 (15.6.2)
The csproj and the following section which should be deleted:
<ItemGroup>
<PackageReference Include="NuGet.Build.Packaging" Version="0.1.227" />
</ItemGroup>
Once this is deleted, creating nuget packages works.
I had this problem because we'd made some changes to be able to create temporary packages.
If you have the tag <PackageVersion> inside your csproj file, you need to update this value to the new version number (or remove the tag).
The UI doesn't change this tag's value, so you have to go via the XML (VS2019).

Nuget: Add file to consuming project?

I would like to add an XSD file to a Nuget package. When a project installs the Nuget package, this file should be included in the project, in order to allow Intellisense in the project's app.config file.
I can add the XSD to the Nuget package just fine, but I don't know how to make it show up in the project that uses the dependency.
Can this be done?
FWIW There are some extra sections injected in the project's app.config file (via Nuget's "transform" capability). The XSD offers Intellisense for those extra sections, and Visual Studio automatically picks up XSD schemas included in the project (or even solution) that match the declared namespace of the XML elements.
Nuget has the option to run custom install Powershell scripts that get a reference to the project that is installing the package.
Details:
http://docs.nuget.org/docs/creating-packages/creating-and-publishing-a-package#Automatically_Running_PowerShell_Scripts_During_Package_Installation_and_Removal
Here are some usage examples:
http://www.codeproject.com/Articles/209522/PowerShell-Script-Examples-for-NuGet-Packages

Resources