I have a very simple post build script which packages all dlls from my project to a custom nuget server. This works fine, however, when opening package manager from any solution, I see the nuget package as a new install, as opposed to the expected 'update' option.
The nuspec file I am using is:
<?xml version="1.0"?>
<package >
<metadata>
<id>Objects.ForConsumers</id>
<version>1.2015.1111.11</version>
<title>Objects.ForConsumers</title>
<authors>My Firm</authors>
<owners>My Firm</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Objects For Consumers</description>
<releaseNotes></releaseNotes>
<copyright>Copyright 2015</copyright>
<tags>Objects For Consumers</tags>
</metadata>
<files>
<file src="*.dll" target="lib" />
</files>
</package>
The version number is incremented with each build.
The commands are essentially
nuget pack Objects.ForConsumers.nuspec
nuget push Objects.ForConsumers.1.2015.1111.12.nupkg -s http://nuget.myserver.com myApiKey
Can anyone suggest which this is happening?
You have selected the "online" option on the panel/tab on the left. If you select "Updates" and search for your package, you should see the update button.
I finally stumbled over the resolution to this. My nuspec file has the following:
<files>
<file src="*.dll" target="lib" />
</files>
I updated this as follows:
<files>
<file src="*.dll" target="lib" />
<file src="*.dll" target="lib/net40" />
</files>
(Adding in the specific folder for my .net version) And all is working now!
Hope this helps somebody else in the future.
Related
I have following dll's among others in a solution:
Base
Core
Basics
R1
R2
Types
I want to put them all in one single nuget package and upload it to Azure DevOps -> Artifacts. Is this possible ?
Is there a way to create a nuget package consisting multiple projects
including some which dont have reference to any other project?
The short answer is Yes, We could use .nuspec to pack up the assemblies:
Download the nuget.exe.
Create a new project.
Open a cmd and switch path to nuget.exe
Use command line: nuget spec "PathOfProject\TestDemo.csproj"
Open the TestDemo.csproj.nuspec file and modify it and add the assemblies as file; below is my .nuspec file:
<?xml version="1.0"?>
<package>
<metadata>
<id>TestDemo</id>
<version>1.0.0</version>
<authors>Tester</authors>
<owners>Tester</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>TestDemo</description>
<releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
<copyright>Copyright 2017</copyright>
<tags>Tag1 Tag2</tags>
</metadata>
<files>
<file src="ThePathOfTheDll\*.Base.dll" target="lib\net461" />
<file src="ThePathOfTheDll\*.Core.dll" target="lib\net461" />
<file src="ThePathOfTheDll\*.Basics.dll" target="lib\net461" />
<file src="ThePathOfTheDll\*.R1.dll" target="lib\net461" />
<file src="ThePathOfTheDll\*.R2.dll" target="lib\net461" />
<file src="ThePathOfTheDll\*.Types.dll" target="lib\net461" />
</files>
</package>
Use pack command: nuget pack TestDemo.csproj.nuspec
Besides, if your project is donet project, you can edit your csproj file, add an ItemGroup to include the dlls as below: This will pack the other dlls along with your current project dll in the nuget package:
<ItemGroup>
<Content Include="<path to other dll>">
<Pack>true</Pack>
<PackagePath>lib\$(TargetFramework)</PackagePath>
</Content>
</ItemGroup>
Bear with me - this is an unusual scenario.
I have 4 projects in my solution. The top most project references the 3 other projects. None of the 3 other projects reference each other. So the architecture is like this:
Now, when I build project A I want it to produce a nuget package containing projects B, C and D but not project A. As this is in .NET standard I can configure the packages tab of project A to produce a nuget package automatically when it builds by checking the 'Generate NuGet package on build option.' Then, I can get it to include B, C and D by making the following changes to A's csproj file:
<ItemGroup>
<ProjectReference Include="..\B.csproj">
<PrivateAssets>all</PrivateAssets>
</ProjectReference>
<ProjectReference Include="..\C.csproj">
<PrivateAssets>all</PrivateAssets>
</ProjectReference>
<ProjectReference Include="..\D.csproj">
<PrivateAssets>all</PrivateAssets>
</ProjectReference>
</ItemGroup>
<PropertyGroup>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
<Version>1.0.0-beta</Version>
<PackageId>A</PackageId>
<Company></Company>
<Product>A</Product>
<Description></Description>
<Authors></Authors>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<Target Name="CopyProjectReferencesToPackage" DependsOnTargets="ResolveReferences">
<ItemGroup>
<BuildOutputInPackage Include="#(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference')->WithMetadataValue('PrivateAssets', 'all'))" />
</ItemGroup>
</Target>
Ideally I would like to add a line to remove A.dll from the nuget package. Is this possible? A is a wrapper project which consuming code will never need to use. It is not possible for B, C and D to reference each other.
UPDATE
This is how I solved it (thanks #tom redfern)
I created a nuspec file manually:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>A</id>
<version>1.0.0-beta</version>
<authors>Foo</authors>
<owners>Bar</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>A package</description>
<dependencies>
<group targetFramework=".NETStandard2.0">
</group>
</dependencies>
</metadata>
<files>
<file src="bin\Release\netstandard2.0\B.dll" target="lib\netstandard2.0\B.dll" />
<file src="bin\Release\netstandard2.0\C.dll" target="lib\netstandard2.0\C.dll" />
<file src="bin\Release\netstandard2.0\D.dll" target="lib\netstandard2.0\D.dll" />
</files>
</package>
Then in my .csproj file for A I put the following to automatically pack it after a build:
<Target Name="__PackNuGetPackage" AfterTargets="Build">
<Exec Command="$(NugetPackage)nuget.exe pack "A.nuspec"" />
</Target>
Using patented(1) elite(2) debugging skills, we can figure out if it's possible without manually creating and maintaining a nuspec file.
First, let's start with NuGet's docs on creating a package with the dotnet CLI. It says "msbuild -t:pack is functionality equivalent to dotnet pack". So, first hint, it's just running MSBuild targets.
So, run dotnet msbuild my.csproj -pp:pp.txt. This "pre-processes" (evaluates all MSBuild import statements and writes the result into a single file) the csproj (just a standard MSBuild file). We then search for the pack target, and scroll up until we find the filename of the file that was imported. We see it's NuGet.Build.Tasks.Pack.targets, and since NuGet is open source on GitHub, I can point you to the source.
Searching NuGet.Build.Tasks.Pack.targets for Condition, to see what extensibility options the NuGet team has provided, I see <IncludeBuildOutput Condition="'$(IncludeBuildOutput)'==''">true</IncludeBuildOutput>. So, settings <IncludeBuildOutput Condition="'$(IncludeBuildOutput)'==''">false</IncludeBuildOutput> in your csproj, might work.
(1) not patented
(2) standard, but since people don't modify MSBuild files anywhere near as often as C#, the skills and tools aren't as well known
You can achieve this by using a nuspec file. Use nuspec when you need absolute control over the nuget pack process. A simple nuspec file:
<package >
<metadata>
<id>MyPackage</id>
<version>1.0</version>
<authors>Something</authors>
<owners>Something</owners>
<description>Somthing</description>
<copyright></copyright>
<dependencies>
<!-- any nuget package dependencies -->
<dependency id="AnotherPackage" version="2019.2.4.1" />
</dependencies>
</metadata>
<files>
<!-- this is where you can have complete control over which assemblies get added to your package. You can add them individually pr using wildcards. -->
<file src="..\obj\**\*.dll" target="lib" />
</files>
</package>
When you have created your .nuspec file, add it into your solution, and then make your "Nuget Pack" build step read the nuspec file rather than the project file.
I've been recently trying to create a .nuspec file that attaches a .dll file as an Embedded Resource. To do so, I've used the contentFiles tag on metadata, setting the buildAction="EmbeddedResource", as described in the section Example contentFiles section on the official documentation.
Below you can see my .nuspec file content:
<package>
<metadata>
<id>MyPackage</id>
<version>1.0.0.0</version>
<title>MyPackage</title>
<authors>Matias G Henschel</authors>
<owners>Matias G Henschel</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>My package description</description>
<copyright>2017</copyright>
<contentFiles>
<files include="myDllFile.dll" buildAction="EmbeddedResource" />
</contentFiles>
</metadata>
<files>
<file src="content\myDllFile.dll" target="contentFiles" />
</files>
</package>
This package correctly copies the file inside the target project, but it doesn't apply the Build Action to it, which is crucial for me.
I've also tried using a .targets file, with no success.
If you want to see more, I've also created an Issue on the GitHub page.
PS: IMHO, both documentation on contentFiles and .targets files require some rework, they aren't clear enough and .targets' lacks examples.
You also need a file entry to actually copy the file to the correct contentFiles folder:
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
…
<contentFiles>
<files include="any/any/MyEmbeddedFile.txt" buildAction="EmbeddedResource" />
</contentFiles>
</metadata>
<files>
<file src="path/to/MyEmbeddedFile.txt" target="contentFiles/any/any/MyEmbeddedFile.txt" />
</files>
</package>
Note that this will only work in NuGet 3.3+ with project.json based projects and NuGet 4+ for PackageReference based projects. For projects using this package via packages.config, you will still need to add the file to the content folder and add a custom target to make it the right item type.
I'm trying to create a NuGet package with the following command:
nuget.exe pack MyBeautiful.nuspec
Which looks like this:
<?xml version="1.0"?>
<package>
<metadata>
...
</metadata>
<files>
<file src="\MyBeautifulApp\bin\Release\*" target="." />
</files>
</package>
With version 3.4.4 of NuGet the generated packaged is 3.8 MB in size but none of my files are included. The NuGet package is empty.
If I try exactly the same with an earlier version of NuGet (3.3.0) my files are included correctly.
Is this a known bug in NuGet 3.4.4 or what am I missing?
Found the issue. This line in the nuspec file:
<file src="\MyBeautifulApp\bin\Release\*" target="." />
Should be:
<file src="\MyBeautifulApp\bin\Release\*" target="" />
So no dot in the target.
I am creating a nuget package that besides other files contains also configuration files such as: f1.config, f2.config etc. These configuration files are in turn referenced in the web.config file.
As these configuration files may or may not exist in the project where this package would be installed, I have renamed them to f1.config.transform, f2.config.transform.
While the installation of the package runs flawlessly in all possible scenarios, uninstalling is not working as expected in one particular case. Namely, if let say the config file f2.config did not exist in the project before the installation, it will not be removed when uninstalling the package.
Any ideas?
EDIT: NuGet spec file
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>WCFServicesProxyPackage</id>
<version>1.0.3</version>
<title />
<authors>Shkelzen a. Saraqini</authors>
<owners>Shkelzen a. Saraqini</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>WCF services proxy package.</description>
<language>en-CA</language>
<references>
<reference file="WCFServices.Proxy.dll" />
</references>
</metadata>
<files>
<file src="content\config\system.serviceModel.behaviors.Local.config.transform" target="content\config\system.serviceModel.behaviors.Local.config.transform" />
<file src="content\config\system.serviceModel.behaviors.Production.config.transform" target="content\config\system.serviceModel.behaviors.Production.config.transform" />
<file src="content\config\system.serviceModel.behaviors.QA.config.transform" target="content\config\system.serviceModel.behaviors.QA.config.transform" />
<file src="content\config\system.serviceModel.bindings.Local.config.transform" target="content\config\system.serviceModel.bindings.Local.config.transform" />
<file src="content\config\system.serviceModel.bindings.Production.config.transform" target="content\config\system.serviceModel.bindings.Production.config.transform" />
<file src="content\config\system.serviceModel.bindings.QA.config.transform" target="content\config\system.serviceModel.bindings.QA.config.transform" />
<file src="content\config\system.serviceModel.client.Local.config.transform" target="content\config\system.serviceModel.client.Local.config.transform" />
<file src="content\config\system.serviceModel.client.Production.config.transform" target="content\config\system.serviceModel.client.Production.config.transform" />
<file src="content\config\system.serviceModel.client.QA.config.transform" target="content\config\system.serviceModel.client.QA.config.transform" />
<file src="content\Web.config.transform" target="content\Web.config.transform" />
<file src="lib\net40\WCFServices.Proxy.dll" target="lib\net40\WCFServices.Proxy.dll" />
</files>
</package>
How do you install/uninstall the config files? Could you share some PowerShell snippets from your scripts (assuming you're using PowerShell install.ps1/uninstall.ps1 scripts in your package)?
Maybe you can force the removal of the files: http://www.timvw.be/2011/10/18/force-the-removal-of-a-file-with-powershell/
Also, it is likely this functionality will be improved in the future, if and when XDT becomes OSS for NuGet to benefit from it.