Getting version in post-build for Nuget - c#

Code:
if $(ConfigurationName) == Release (
cd $(ProjectDir)
nuget spec Entities -f
nuget pack DeusPak.Entities.csproj -Prop Configuration=Release
nuget push DeusPak.Entities.$(version).nupkg $(MYGET_API_KEY) -Source http://www.myget.org/F/lojaali/api/v2/package
)
I have just started to play around with NuGet and want to know how to include the version number in my NuGet package. I am currently hard coding it into the post-build event which is obviously not what I want to keep doing. Can anybody help?
This is my current post-build event :
if $(ConfigurationName) == Release (
cd $(ProjectDir)
nuget spec Dev-f
nuget pack Dev.csproj -Prop Configuration=Release
nuget push Dev.1.0.0.0.nupkg $(MYGET_API_KEY) -Source http://www.myget.org/F/api/v2/package
)
Update:
OK, I have managed to build the DLL with the correct auto incremented version number :
if $(ConfigurationName) == Release (
cd $(ProjectDir)
nuget spec Dev -f
nuget pack Dev.csproj -Prop Configuration=Release
nuget push Dev.$(version).nupkg $(MYGET_API_KEY) -Source http://www.myget.org/F/api/v2/package
)
But this version does not show on my list of MyGet packages. How do I get it to show there so it can be downloaded? Or can this only be done manually by clicking 'Add a package'?

Just extending a bit the solution provided by Carlos J López, i used the AfterBuild script to actually call NuGet and provide the version parameter.
In my case, I also added "cd $(ProjectDir)" to the post build event, which actually happens before the AfterBuild script.
Cheers,
<Target Name="AfterBuild" Condition="'$(Configuration)' == 'Release'">
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
<Output TaskParameter="Assemblies" ItemName="AssemblyVersion" />
</GetAssemblyIdentity>
<Exec Command="$(SolutionDir)\.nuget\nuget pack $(ProjectName).nuspec -Version %(AssemblyVersion.Version)" />
<Message Text="$(SolutionDir)\.nuget\nuget pack $(ProjectName).nuspec -Version %(AssemblyVersion.Version)" Importance="high" />
</Target>

It is not clear in your question, but assuming you want to sync the version of your package with the version of your assembly, you can simply manage the AssemblyVersion attribute in the project's AssemblyInfo.cs file.
[assembly: AssemblyVersion("1.0.0")]
or if you want to use auto-generated build numbers
[assembly: AssemblyVersion("1.0.0.*")]
If you want to deviate from the assembly's version, and only specify the package version, you can use the AssemblyInformationalVersion attribute in the AssemblyInfo.cs file.
[assembly: AssemblyInformationalVersion("1.0.0")]
It's also not clear from the question what versioning strategy you use, but I'll assume you want to apply Semantic Versioning (where the first 3 version numbers are most relevant). In general when auto-creating NuGet packages, I'd recommend you to create a tokenized nuspec file in your csproj directory, so you can more easily manipulate the package metadata. FYI, there's even a NuGet package to assist you with that:
Install-Package NuSpec
NuGet will look for this nuspec (make sure it's called MyProject.nuspec) when targeting MyProject.csproj.
<package>
<version>$version$</version>
...
</package>
I also explained this on the MyGet blog in this post: http://blog.myget.org/post/2012/04/27/NuGet-version-token-explained.aspx
A post build that calls nuget pack should be good enough then, assuming you simply change the assembly version before building.
nuget pack MyProject.csproj

This is how you can get a $(version) variable in your after build event, which should be as good as post build.
<Target Name="AfterBuild" Condition="'$(Configuration)' == 'Release'">
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
<Output TaskParameter="Assemblies" ItemName="AssemblyVersion" />
</GetAssemblyIdentity>
<Exec Command="echo %(AssemblyVersion.Version)" />
<Message Text="Released %(AssemblyVersion.Version)" Importance="high" />
</Target>
So you would have to modify your .csproj file since VS does not provide an UI for that.

Related

Can I create a Nuget package for a C# project that includes its project dependencies without also creating separate packages for those dependencies? [duplicate]

I want to run a local/internal NuGet repository. I think I've figured out how to "reuse" existing NuGet packages by including them in a dummy project using NuGet and scanning the package file to grab my locally-cached .nupkg files, but...
How do you create a nuget package (.nupkg) from a project, automatically including all dll dependencies and not just those grabbed via NuGet?
Specifically:
Create a solution
Add a new Project
Add references to various .dll files/other projects <-- this is the missing part
Add NuGet packages via package manager / cmdline / whatever
something automatically creates the .nupkg
From what I've found, you're supposed to do things like
manually edit your .csproj file to add <BuildPackage>true</BuildPackage> to include dependencies
manually create a .nuspec file and manually list your dependencies (similar ?)
manually run nuget pack on your .nuspec file
But everything is manual, which is stupid. Even the semi-automatic solutions are still awkward or half-manual:
Create .nuspec templates - doesn't seem to include dependencies, just metadata
nuget pack via build-event (step #5), which you need to add manually to every project, and it has its own quirks:
"$(SolutionDir).nuget\NuGet.exe" pack "$(ProjectPath)" -Properties Configuration=Release
move /Y *.nupkg "$(TargetDir)"
I'll settle for something that automatically creates a .nuspec manifest from project references. Then theoretically that + the nuget build-event can be rolled up into a build-project/nuget package, which is what I really want to see.
Your point #3 (Add references to various .dll files/other projects <-- this is the missing part) really contains two different issues: (1) add references to various dll files, and (2) add references to other projects in the same solution.
Number (2) here has gotten some added support as of NuGet 2.5. You can add an option to include references to other projects in the same solution when creating a NuGet package for a project:
nuget pack projectfile.csproj -IncludeReferencedProjects
If projectfile.csproj references any other projects in your solution that also is exposed as NuGet packages, these projects' NuGet packages will be added as dependencies.
If it references projects in your solution that doesn't expose themselves as NuGet packages, their dlls will be included in this NuGet package.
As for (1), if you find yourself often adding dlls to your projects that aren't available as NuGet packages, you could just create your own (internal) NuGet packages with these files. If you then add these dlls as a NuGet package instead of the files directly, this NuGet package will be a dependency in your project's NuGet package.
I found a well-written article on this topic. I have the same issue with certain packages that have a hierarchy of dependencies and up until now I've been uploading each as a separate NuGet package (what. a. waste. of. time)
I've just tested the solution found here: https://dev.to/wabbbit/include-both-nuget-package-references-and-project-reference-dll-using-dotnet-pack-2d8p
And after examining the NuGet package using NuGet Package Explorer, the DLLs produced by referenced projects are indeed present. I'm going to test by actually submitting this package to NuGet and testing it.
Here's my source in case it is helpful to you: https://github.com/jchristn/NuGetPackTest
And the test NuGet package: https://www.nuget.org/packages/NuGetPackTest/1.0.0
The solution appears to work well. I don't know what it's going to look like when there are layers of references, I'm sure it could get really hairy and really fast.
.csproj from NuGetPackTest library which references project TestLibrary (portions removed for brevity)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netcoreapp3.0;netcoreapp3.1;net461</TargetFrameworks>
...
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<!-- added this line -->
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<ItemGroup>
<!-- modified this ProjectReference to include the children ReferenceOutputAssembly and IncludeAssets -->
<ProjectReference Include="..\TestLibrary\TestLibrary.csproj">
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<IncludeAssets>TestLibrary.dll</IncludeAssets>
</ProjectReference>
</ItemGroup>
<!-- added this section -->
<Target DependsOnTargets="ResolveReferences" Name="CopyProjectReferencesToPackage">
<ItemGroup>
<BuildOutputInPackage Include="#(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))"/>
</ItemGroup>
</Target>
</Project>
For other Googlers, you can use this if you are using the NuGet.targets file to run NuGet Pack:
<Target Name="PrePackage" BeforeTargets="BuildPackage">
<PropertyGroup>
<BuildCommand>$(BuildCommand) -IncludeReferencedProjects</BuildCommand>
</PropertyGroup>
</Target>
Check this out!
The solution which I found is an extension for Visual Studio:
https://visualstudiogallery.msdn.microsoft.com/fbe9b9b8-34ae-47b5-a751-cb71a16f7e96/view/Reviews
You simply add new project called NuGet Package:
Then you are adding interesting you projects to references and BOOOM !!
All dependencies and file directories are automatically added.
If you want to modify NuSpec data you click right at project and go to Properties,
then modify what you want.
Generated NuSpec and nupkg will be in folder obj of your new project.
I hope it helps ;).
I solved this for my case by adding the whole TargetDir to the nuget package.
Just add this to the .csproj :
<Target Name="IncludeAllFilesInTargetDir" AfterTargets="Build">
<ItemGroup>
<None Include="$(TargetDir)\**">
<Pack>true</Pack>
<PackagePath>tools</PackagePath>
</None>
</ItemGroup>
</Target>

How can I wrap C# DLLs into a NuGet package on Ubuntu?

On Ubuntu I'd like to wrap a few C# DLL files into a NuGet package. On Windows one would use the NuGet package explorer or nuget.exe + manually edited *.csproj.nuspec. In summary when manually editing the *.nuspec file one may add DLLs via the <files> section:
<files>
<file src="some\Path\YourDll.dll" target="lib"></file>
</files>
On Ubuntu I'd like to use dotnet pack instead. However it seems like it's not able to operate on a *.csproj.nuspec file:
Usage: dotnet pack [options] <PROJECT | SOLUTION>
Arguments:
<PROJECT | SOLUTION> The project or solution file to operate on. If a file is not specified, the command will search the current directory for one.
Options:
-h, --help Show command line help.
-o, --output <OUTPUT_DIR> The output directory to place built packages in.
--no-build Do not build the project before packing. Implies --no-restore.
--include-symbols Include packages with symbols in addition to regular packages in output directory.
--include-source Include PDBs and source files. Source files go into the 'src' folder in the resulting nuget package.
-c, --configuration <CONFIGURATION> The configuration to use for building the package. The default for most projects is 'Debug'.
--version-suffix <VERSION_SUFFIX> Set the value of the $(VersionSuffix) property to use when building the project.
-s, --serviceable Set the serviceable flag in the package. See https://aka.ms/nupkgservicing for more information.
--nologo Do not display the startup banner or the copyright message.
--interactive Allows the command to stop and wait for user input or action (for example to complete authentication).
--no-restore Do not restore the project before building.
-v, --verbosity <LEVEL> Set the MSBuild verbosity level. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].
--runtime <RUNTIME_IDENTIFIER> The target runtime to restore packages for.
--no-dependencies Do not restore project-to-project references and only restore the specified project.
--force Force all dependencies to be resolved even if the last restore was successful.
This is equivalent to deleting project.assets.json.
Can I wrap C# DLLs into a NuGet package on Ubuntu using the dotnet CLI? Or do I have to use the nuget CLI (apt-get install nuget) instead with the approach like on Windows?
I would add this into the .csproj file:
<ItemGroup>
<Content Include="some.dll" PackageCopyToOutput="true">
<pack>true</pack>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
It's not pretty but it works.

Include ONLY .xml file of SPECIFIC nuget package in a different folder

We have a project (ProjectAbc) in a solution which is referencing a nuget package (which is our different project [ProjectXyz] from other solution). We use .net core framework and package reference to include nuget package (ProjectXyz) in .csproj file.
<PackageReference Include="ProjectXyz" Version="1.1.2.3" />
When the solution is build locally or in Prod, ProjectXyz.dll and ProjectXyz.xml gets generated in
ProjectAbc/bin/debug(locally) or release(inProd)/netcoreapp3.1
We want Only ProjectXyz.xml of Only ProjectXyz nuget package to get generated in following folder directly
ProjectAbc
I found various articles which directed me to do different things like copying file to output directory after building or using relative path. Though, tried different ways, I keep getting various errors. It may be because I am not aware of the syntax in .csproj file or also may be because I am not sure what I am doing.
What would be best way to copy file in above case or to generate file directly in the required folder?
for my comment response:
Since I am unable to paste the screenshot in my comment for #Perry Qian-MSFT. So pasting it here.
8/20/2020-----package screenshot---------------------------
You could use <package_name>.props file in nuget project ProjectXyz to copy such file into the project folder of ProjectAbc. You should use <package_id>.props.
1) First, in your ProjectXyz project, create a folder called build and then add a file called <package_id>.props, in your side, it is called ProjectXyz.props.
2) Add these in ProjectXyz.props file:
<Project>
<Target Name="CopyFilesToProject" BeforeTargets="Build">
<Message Text="Copying ProjectXyz.xml to project" />
<ItemGroup>
<SourceScripts Include="$(MSBuildThisFileDirectory)..\..\content\any\any\**\*.*"/> //file from the ProjectXyz nuget package
</ItemGroup>
<Copy
SourceFiles="#(SourceScripts)"
DestinationFiles="#(SourceScripts -> '$(MSBuildProjectDirectory)\%(RecursiveDir)%(Filename)%(Extension)')" //copy into the main ProjectAbc project folder
/>
</Target>
</Project>
3) Unload your ProjectXyz project and add these in ProjectXyz.csproj file:
<ItemGroup>
<Content Include="bin\Debug\xxx\ProjectXyz.xml(the path of the ProjectXyz.xml)" Pack="true"
PackagePath="content\any\any;contentFiles\any\any\;;">
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>
<None Include="build\ProjectXyz.props" Pack="true" PackagePath="build\$(TargetFramework)"/>
</ItemGroup>
4) Then you should pack your new ProjectXyz project.
5) Then you finish packing, you should first clean all nuget caches first.
Then in your ProjectAbc project, you should uninstall the old one and then install the new ProjectXyz nuget package.
After that, you should build ProjectAbc project first and then you will see that xml document from the nuget package is under the project folder of ProjectAbc.
====================================================================
Update 1
ProjectXyz project is net core or net standard while ProjectAbc is net core.
First, to help you understand the issue, instead, I try to pack ProjectXyz.xml file into other folder in the ProjectXyz.nupkg.
1) First, change to use these xml content in ProjectXyz.csproj file:
<ItemGroup>
<Content Include="bin\Debug\netcoreapp3.1\ProjectXyz.xml" Pack="true" PackagePath="XmlFolder">
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>
<None Include="build\ProjectXyz.props" Pack="true" PackagePath="build\$(TargetFramework)"/>
</ItemGroup>
The goal of it is to pack ProjectXyz.xml file into the folder called XmlFolder of XmlFolder.nupkg. And save ProjectXyz.xml file in the Nuget package.
Make sure that the file exists in the nuget package.
If the file does not exist, I think it is controlled by your git. Or you could put this ProjectXyz.xml in your project folder.
Try to right-click on your project-->Properties-->Build-->check this:
Just use <Content Include="ProjectXyz.xml" Pack="true" PackagePath="XmlFolder">
In our side, the file can be copied into nupkg nuget package so you should make sure that other tools like git will not interface it.
2) Then change to use these in ProjectXyz.props file:
<Project>
<Target Name="CopyFilesToProject" BeforeTargets="Build">
<Message Text="Copying ProjectXyz.xml to project" />
<ItemGroup>
//ProjectXyz.xml file from the ProjectXyz nuget package
<SourceScripts Include="$(MSBuildThisFileDirectory)..\..\XmlFolder\**\*.*"/>
</ItemGroup>
//copy ProjectXyz.xml file into the main ProjectAbc project folder
<Copy
SourceFiles="#(SourceScripts)"
DestinationFiles="#(SourceScripts -> '$(MSBuildProjectDirectory)\%(RecursiveDir)%(Filename)%(Extension)')"
/>
</Target>
</Project>
The goal of it is that when you install this nuget package, it will first run this target to copy the ProjectXyz.xml file from the nuget package into the main project ProjectAbc.
Note:
When you finishing installing nuget package, first build ProjectAbc project and the file will exists in ProjectAbc project folder.
3) Then right-click ProjectXyz-->Properties-->Pack to pack your project.
When you install the new ProjectXyz, you should first delete all files under
C:\Users\xxx(current user)\.nuget\packages.
Also, one more question I had is, the ProjectXyz is being referenced
in multiple projects like ProjectAbc, Project123. We dont want
ProjectXyz.xml file to show up in Project123 but only in ProjectAbc. I
guess with above solution, it might show in both of referencing
projects.
For this, you only need to add a condition in CopyFilesToProject target like this: $(ProjectXyz_Flag)==true and then create a property ProjectXyz_Flag and set its value to true in ProjectAbc.csproj file.
When you build ProjectAbc project, it will determine whether to copy the file based on the switch variable you are currently setting.
a) Add a condition called $(ProjectXyz_Flag) in ProjectXyz.props file:
Then repack your ProjectXyz project and do several clean steps as I said before.
When you install that package in ProjectAbc project, you should add such such property in ProjectAbc.csproj file:
<PropertyGroup>
<ProjectXyz_Flag>true</ProjectXyz_Flag>
</PropertyGroup>
Then when you build ProjectAbc project, it will execute the copy target and if you do not define that property, it will not copy that file in ProjectAbc.
And if those projects do not need ProjectXyz.xml file, you just do not define that switch property in those projects.
====================================================
Update 2
try to use nuget.exe cli to pack your project, you just need a custom nuspec file:
First, download nuget.exe cli and then configure its local path into PATH System Environment Variable. Then, you can call nuget in CMD.
Second, open CMD and cd xxx(project folder path), run nuget spec to generate the nuspec file and then modify the generated nuspec file:
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<!-- ... -->
</metadata>
<files>
<file src="xxx\ProjectXyz.xml" target="XmlFolder" />
<file src="build\ProjectXyz.props" target="build\netcoreapp3.1" />
</files>
</package>
Third, run nuget pack to pack this project.
==============================================================
Update 3
Please first clean your nuget caches or just delete all nuget caches under C:\Users\xxx(current user)\.nuget\packages. Then reinstall your nuget package.
Also, make sure that the xxx.props name is the same as your nuget package_id.
If your nuget package calls ProjectXyz(package_id). Then the props file should be named as ProjectXyz.props.
Besides, you should set msbuild project build output verbosity to detailed under Tools-->Options-->Projects and Solutions-->Build and Run.
Then, rebuild your ProjectAbc to check whether the target executes.
======================================================
Update 4
You should make sure that when you pack your package project.mnop, make sure that the project.mnop.props file has no syntax errors.
For an example, I have incorrectly wrote something like asdczxcx in the props file, however, since the build action of the props file is Content or None, Vs will not automatically analyze its errors and will not show the errors.
And the error shows the same as yours.
So you should delete that Illegal characters. Make sure that project.mnop.props has no syntax errors. Then repack your project.
After that, first uninstall the old nuget package project.mnop on the ProjectAbc.
Then, delete the cache project.mnop folder under C:\Users\xxx(current user)\.nuget\packages.
Finally, delete bin and obj folder of ProjectAbc, install the new version project.mnop, then rebuild your project ProjectAbc.
=============================================
Update 5
Actually, this should be an easier way. And your inspiration can be done with a more concise Nuget package structure.
You should only change this:
1) change to use ProjectXyz.xml from the lib folder in your ProjectXyz.props:
<SourceScripts Include="$(MSBuildThisFileDirectory)..\..\lib\netcoreapp3.1\ProjectXyz.xml"/>
</ItemGroup>
<Copy
SourceFiles="#(SourceScripts)"
DestinationFiles="#(SourceScripts -> '$(MSBuildProjectDirectory)\%(RecursiveDir)%(Filename)%(Extension)')"
/>
2) change your xxx.nuspec file to:
<?xml version="1.0"?>
<package >
<metadata>
........
<copyright>Copyright 2020</copyright>
<tags>Tag1 Tag2</tags>
</metadata>
<files>
<file src="build\ProjectXyz.props" target="build\netcoreapp3.1" />
</files>
</package>
3) then pack your project and then you can get what you want.
Note: SourceScripts uses the path $(MSBuildThisFileDirectory).
$(MSBuildThisFileDirectory) means the full path where the ProjectXyz.props file of the nuget package exists.
In your side, the $(MSBuildThisFileDirectory) means
C:\Users\xxxxx\.nuget\packages\project.mnop\45.0.0\build\netcoreapp3.1
And then use this path to find the file address of ProjectXyz.xml in the lib folder of the nuget package.

Nuget package does not restore all DLLs and Dependencies

I have created a Nuget package using Nuget Package Explorer. The package has some third party dlls that I use in my code. I dlls are included in the Nuget package and not referenced directly in the project references. The Nuget Package has the following.
- thirdPartyAAA.dll
- thirdPartyAAA.xml (Needed by thirdPartyAAA.dll)
- thirdPartyBBB.dll (needed by thirdPartyAAA.dll
- thirdPartyBBB.dll.config (used by thirdPartyBBB.dll)
- Dependency on HtmlAgilityPack nuget (Needed by thirdPartyAAA.dll)
- Dependency om RestSharp nuget (Needed by thirdPartyAAA.dll)
The problem is: when I reference this Nuget package in the code and compile the code I only get aaa.dll in the bin output folder. the following files are missing from the bin folder:
- thirdPartyAAA.xml
- thirdPartyBBB.dll
- thirdPartyBBB.dll.config
- All dlls from HtmlAgilityPack nuget
- All dll from RestSharp nuget
In my code I directly reference thirdPartyAAA.dll.
Is there a way - either during creating the Nuget Package or when referencing the package - to force the Nuget Package to restore all its contents and its dependencies? I need all the files that's included in the Nuget Package to be restored regardless if they are directly references in the code or not.
thank you all for your help.
Here is the manifest of the package if it helps.
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>MyPackage</id>
<version>1.0.0</version>
<title></title>
<authors>Dev</authors>
<owners>Dev</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>My package description.</description>
<dependencies>
<dependency id="HtmlAgilityPack" version="1.4.9" />
<dependency id="RestSharp" version="105.0.1" />
</dependencies>
</metadata>
<files>
<file src="content\thirdPartyAAA.chm" target="content\thirdPartyAAA.chm" />
<file src="content\thirdPartyAAA.XML" target="content\thirdPartyAAA.XML" />
<file src="content\thirdPartyBBB.dll.config" target="content\thirdPartyBBB.dll.config" />
<file src="lib\thirdPartyAAA.dll" target="lib\thirdPartyAAA.dll" />
<file src="lib\thirdPartyBBB.dll" target="lib\thirdPartyBBB.dll" />
</files>
</package>
The problem is: when I reference this Nuget package in the code and compile the code I only get aaa.dll in the bin output folder. the following files are missing from the bin folder:
- thirdPartyAAA.xml
- thirdPartyBBB.dll
- thirdPartyBBB.dll.config
- All dlls from HtmlAgilityPack nuget
- All dll from RestSharp nuget
First, for the thirdPartyBBB.dll, you should make sure the target framework version of project is higher than your dll's target framework. For example, If the target framework version of your project is .net 4.6.2, the target framework version of your thirdPartyBBB.dll should be lower than .net 4.6.2. Otherwise, you are referring a dll file with higher version target framework to the project with lower version target framework. This is incompatible.
Besides, for the dependencies of this package, you can check if those dependencies added to the project, and the properties Copy Local of those dlls are set to True. It works fine on my side.
Second, for the content file, you should add a .targets file in the build folder in your package with following code to copy those content files to the bin folder:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="$(ProjectDir)thirdPartyAAA.chm">
<Link>thirdPartyAAA.chm</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CustomToolNamespace></CustomToolNamespace>
</None>
<None Include="$(ProjectDir)thirdPartyAAA.XML">
<Link>thirdPartyAAA.XML</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CustomToolNamespace></CustomToolNamespace>
</None>
<None Include="$(ProjectDir)thirdPartyBBB.dll.config">
<Link>thirdPartyBBB.dll.config</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CustomToolNamespace></CustomToolNamespace>
</None>
</ItemGroup>
</Project>
For some details info, please check this thread.
Alternatively, you can use Install.ps1 file to change the property, the script looks like:
param($installPath, $toolsPath, $package, $project)
function MarkDirectoryAsCopyToOutputRecursive($item)
{
$item.ProjectItems | ForEach-Object { MarkFileASCopyToOutputDirectory($_) }
}
function MarkFileASCopyToOutputDirectory($item)
{
Try
{
Write-Host Try set $item.Name
$item.Properties.Item("CopyToOutputDirectory").Value = 2
}
Catch
{
Write-Host RecurseOn $item.Name
MarkDirectoryAsCopyToOutputRecursive($item)
}
}
#Now mark everything in the a directory as "Copy to newer"
MarkDirectoryAsCopyToOutputRecursive($project.ProjectItems.Item("TheFolderOfYourContentFiles"))
You can check similar issue for details.
In addition, I have created a test nuget package, you can check if it works for you, test it with .net framework project with target framework 4.6 and above.
https://1drv.ms/u/s!Ai1sp_yvodHf1QJriMiGQWdYveRm
Hope this helps.
Go to your solution explorer ,
on Ur project references,
right click on the DLL which is missing from the bin folder. Select properties, then make "copy local " to true. This will copy the DLL to the build path after compiling.
Go to your solution explorer ,
on Ur project references,
right click on the DLL which is missing from the bin folder. Select properties, then make "copy local " to true. This will copy the DLL to the build path after compiling.
For nuget restoring please refer the below link
https://learn.microsoft.com/en-us/nuget/consume-packages/package-restore-troubleshooting
I recently ran into almost exactly the same problem.
After 2 days, I discovered several posts that clarified that the contents folder are ONLY deployed during the +initial+ installation of the nuget.
What this means is that any files deployed as CONTENT are intended to be checked into your version control system, just like any other code in your project.
They are specifically NOT deployed when VS runs a "package restore" as it does when you build a project and some packages are missing.

Updating local nuget package on post-build event

I have my local nuget library repository separately both for my personal and work releted class libraries.
I have created some of the nuget packages for the libraries which are no longer in development. I did this only for them because I do not know how to update them automatically as soon as my project builds.
I have figured that all the work is being done by nuget command line with Visual Studio Command Prompt. So I can easily do the work I needed (of course I would know commands perfectly and I do not !)
Basically I want the following tasks to execute on the post-build event of my project.
On project build:
copying project dll into a specific folder (lib folder of the nuget package)
updating nuspec file for new file version (my project is increasing the file version on every build)
creating new nupkg file with new file version
Phil Haack shows some of this feature but it is still a prototype as far as I can tell.
So my requirement is the above. Has anyone else accomplished this?
The selected solution looks like it would work but it seems like there is a simpler solution for your requirements.
You can create a nuspec file that will read data from the project's metadata. You only need to do this once with this command:
C:\<Path to project>\nuget spec
This creates 'tokens' in the spec file that will will be replaced by the project's metadata when you create the nuget package. This includes the file version. You will want to replace and because all projects are technically suppose to have them.
More details can be found here: http://docs.nuget.org/docs/creating-packages/Creating-and-Publishing-a-Package#From_a_project
Then...
For .Net Framework (old-school) projects, in you project's Post build events you can do this:
nuget pack "$(ProjectPath)"
xcopy "$(TargetDir)*.nupkg" "<path where you are hosting your local nuget repo>" /C /Y
(assuming nuget.exe is available on your system PATH).
For .Net Core and Standard projects, nuget can't pack them (see https://github.com/NuGet/Home/issues/4491). Instead, use this as your post-build step:
dotnet pack "$(ProjectPath)" --no-build --include-source --include-symbols --output "<path where you are hosting your local nuget repo>"
Of course you can adjust the options to meet your needs. See https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-pack?tabs=netcore2x for dotnet pack command options.
Just in case someone else (like me) come across this ancient question - in the current era (VS2017, SDK/NugetReference format/ .NET Core / .NET Standard / Multi-target projects), where creation of NuGet package is an option in the Project Properties - so, only issue of local repository has to be solved:
If you have single-target project, to copy your .nupkg file to local NuGet repository, add Post-build event (Project properties > Build Events > Post-build event command line):
xcopy $(TargetDir)*.nupkg [path to your local nuget repository] /s
Like:
xcopy $(TargetDir)*.nupkg G:\imbVelesOpenSource\LocalNuGet\imbVelesSecondGeneration\ /s
If you have multi-target project, to copy your .nupkg file to local NuGet repository:
add Post-build event (Project properties > Build Events > Post-build event command line):
xcopy $(TargetDir)..*.nupkg [path to your local nuget repository] /s
Like:
xcopy $(TargetDir)..*.nupkg G:\imbVelesOpenSource\LocalNuGet\imbVelesSecondGeneration\ /s
Update:
Forget post-build events, there is a cleaner way (xcopy approach works strange for multi-target projects), just add this in project XML:
<Target Name="CopyPackage" AfterTargets="Pack">
<Copy SourceFiles="$(OutputPath)$(PackageId).$(PackageVersion).nupkg" DestinationFolder="G:\imbVelesOpenSource\LocalNuGet\imbVelesSecondGeneration\" />
</Target>
Update
For newer NuGet versions, which cut off the last 0 (patch from a 0.0.0.0 version notation), you will need to regex the PackageVersion:
<Target Name="CopyPackage" AfterTargets="Pack">
<Copy SourceFiles="$(OutputPath)$(PackageId).$([System.Text.RegularExpressions.Regex]::Replace("$(PackageVersion)", "^(.+?)(\.0+)$", "$1")).nupkg" DestinationFolder="G:\imbVelesOpenSource\LocalNuGet\imbVelesSecondGeneration\" />
</Target>
Jeremy Skinner has written a blog post on how he performs automated builds of packages and uploads them to the NuGet Gallery. I think that it matches your requirements.
Basically he uses MsBuild to apply the version (with the MsBuild Community Extensions UpdateXml task) to the nuspec file and invoke the nuget.exe to package it up.
I recently published a solution for this that actually creates/updates the nuspec files during the build, so don't have to do so manually, then creates the nupkg files.
All you will have to add is a post-build event for copying the packages to their destination (or add it as an optional stage to my solution).
You can find an article with a walk-through guide here and the source code + binary here.
With the latest nuget package format using "PackageReference" tags you can use the following simple postbuild event in your csproj to update nuspec file with latest dependencies.
<Target Name="AfterBuild">
<WriteLinesToFile File="dependencies.xml" Overwrite="true" Lines=""/>
<WriteLinesToFile File="dependencies.xml" Overwrite="false" Lines="<dependencies>"/>
<WriteLinesToFile File="dependencies.xml" Overwrite="false" Lines="<dependency id="%(PackageReference.Identity)" version="%(PackageReference.Version)" />" />
<WriteLinesToFile File="dependencies.xml" Overwrite="false" Lines="</dependencies >"/>
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted -command "$xml = [xml] (Get-Content Project.nuspec); $xml.package.metadata.RemoveChild($xml.package.metadata.dependencies); $dependencies = [xml](Get-Content dependencies.xml); $xml.Package.Metadata.AppendChild($xml.ImportNode($dependencies.Dependencies, $true)); $xml.Save('Project.nuspec')""/>
<Delete Files="dependencies.xml" />
</Target>
Only premise for this is that you have a nuspec file with rest of the metadata mentioned in the project directory. Here is a sample nuspec file:
<?xml version="1.0"?>
<package>
<metadata>
<id>Package Id</id>
<version>1.0.0</version>
<authors>Author name</authors>
<owners>Owner name</owners>
<description>Description</description>
<contentFiles>
<files include="**/content.zip" buildAction="None" copyToOutput="true" flatten="false" />
</contentFiles>
<dependencies>
</dependencies>
</metadata>
<files>
<file src="bin\Release\Project.dll" target="lib\net462" />
<file src="bin\Release\Project.pdb" target="lib\net462" />
<file src="bin\Release\file.zip" target="Content" />
</files>
</package>
I solved it by using a command line
Let's assume you have added the location of NuGet to your path environment or copies a stable version to a given directory (this is what I did)
I have my NuGet.exe as well as my certificate in a folder named D:\Build, you may need to update this to fit your path.
Then let's assume you have a codesign certificate file named: "CodeSignCertificate.pfx"
with a password: pa$$w0rd
You can get a simple codesign certificate for 17 euro from Ascertia. they also have free trial certificates that are valid for 10 days. the link https://account.ascertia.com/onlineCA/default
then as a one liner I use :
for %f in (X:\Packages\*.nupkg) do D:\Build\nuget sign %f -CertificatePath D:\Build\CodeSignCertificate.pfx -Timestamper http://timestamp.digicert.com -CertificatePassword pa$$w0rd
This sign all my packages in my output directory
if you only want to sign the lastest the NuGet package as this might be the one you just compiled then you can use something like this.
set Path="X:\ASP-WAF\DLL"
for /f "tokens=*" %%a in ('dir /A:-D /B /O:-D /S %Path%') do set NEW=%%a&& goto:n
:n
sign %NEW% -CertificatePath D:\Build\CodeSignCertificate.pfx -Timestamper http://timestamp.digicert.com -CertificatePassword pa$$w0rd
it's not a one-line but you can put it in a bat file and call that in your post build.

Categories

Resources