'Setting the version number for .NET Core projects - CSPROJ - not JSON projects

This question is very similar to Setting the version number for .NET Core projects, but not the same. Using the latest stable version of .NET Core at the time of writing (1.1) and VS2017, .NET Core has switched from JSON based project files to CSPROJ files.

So - what I am trying to do is set up a CI environment where I would like to be able to modify something prior to a build to stamp my builds with the correct version number.

If I use the attributes like this the old (SharedAssemblyInfo.cs trick):

[assembly: AssemblyFileVersion("3.3.3.3")]
[assembly: AssemblyVersion("4.4.4.4")]

somewhere in the project, I get
CS0579 - Duplicate 'System.Reflection.AssemblyFileVersionAttribute'
and
CS0579 - Duplicate 'System.Reflection.AssemblyVersionAttribute'
errors when building.

When digging into it a bit, I find that there is a file which looks like this generated during the build process (it doesn't exist before I build) in \obj\Debug\netcoreapp1.1:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Reflection;

[assembly: System.Reflection.AssemblyCompanyAttribute("TestApplication")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyDescriptionAttribute("Package Description")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.1.99.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.1.99")]
[assembly: System.Reflection.AssemblyProductAttribute("TestApplication")]
[assembly: System.Reflection.AssemblyTitleAttribute("TestApplication")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.1.99.0")]

// Generated by the MSBuild WriteCodeFragment class.

Question - How do I do this bit?
So I can see that this must somehow be generated from the values entered in the project properties 'package page', but I don't know what the right way would be to change these values on my CI machine.

Ideally, I'd like to be able to specify all this information in my (Jenkins) CI script, but I'd settle for just being able to set the version number.

EDIT - More Info
After reading the first answer, I wanted to make it clear that I am creating both services and NuGET packages - and I would prefer to have 1 way of versioning everything, which would be like the old JSON project where I could just update a single file.

UPDATE I am going with scripting a change to the CSPROJ file which in my opinion is rather hacky as the section I need to modify looks like this...

<PropertyGroup>
 <OutputType>Exe</OutputType>
 <TargetFramework>netcoreapp1.1</TargetFramework>
 <Version>1.0.7777.0</Version>
 <AssemblyVersion>1.0.8888.0</AssemblyVersion>
 <FileVersion>1.0.9999.0</FileVersion>
 <Company>MyCompany</Company>
 <Authors>AuthorName</Authors>
 <Product>ProductName</Product>
 <Description />
 <Copyright>Copyright © 2017</Copyright>
</PropertyGroup>

So - the problem here is that there are multiple 'PropertyGroup' elements; the others appear to be labelled - but not knowing how the CSPROJ is put together, I can't say this will always be the case.

I am working on the premise that the package details will always be filled in, otherwise the value tags (above) don't appear in the XML - so then I can use a script to update the values in place. If the value tags were not there, I would have no clear idea which PropertyGroup element to insert the values into (and also which order, as this appears to be important; changing the order stopped me from loading the project in VS2017).

I am still holding out for a better solution than this one!

Update: After someone marking this question as a possible duplicate (Auto Versioning in Visual Studio 2017 (.NET Core)) - I hadn't seen this question before and now reading it seems to be almost the same except that I dont just want to set the version number. Also, the answers to this question do not solve my problem - only asks what I asked in my question. The accepted answer to my question is exactly the answer I need to solve my problem - so while the other question came first and appears the same - it does not help me at all. Maybe a mod can help?



Solution 1:[1]

dotnet build /p:AssemblyVersion=1.2.3.4

Does that work for you?

Solution 2:[2]

In my case, the main key was /property:Version=1.2.3.4. And the following command line did the job:

dotnet build SolutionName.sln -c Release /property:Version=1.2.3.4

This will override Assembly default version.

Update

So in addition just to clarify this in a practical use case of software release.

For instance when you publish a software you can set File version and Product version as mentioned here.

lets take an example:

dotnet publish .\ProjectFolder\Project.csproj -r win-x64 /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true --self-contained true -o ReleaseFolderName -c Release /p:AssemblyVersion=1.2.3.4 /p:Version=1.2.3.4-product-version

will publish software, when right click on software and click on Details, you get following picture:

Software Details

Solution 3:[3]

For those looking for a different automated (CI) way to do this, consider using conditionals in the .csproj file based on environment variables. For example, you might normally have a hardcoded version prefix and a timestamp-based suffix. But for proper releases, you would want to replace both with a single version that you set during the CI build. To do this, you can set an environment variable before calling dotnet build: let's say, RELEASE_VERSION.

In the .csproj file, under a <PropertyGroup>, you would have the following:

<Version Condition="'$(RELEASE_VERSION)' != ''">$(RELEASE_VERSION)</Version>
<VersionPrefix Condition="'$(RELEASE_VERSION)' == ''">0.0.1</VersionPrefix>
<VersionSuffix Condition="'$(RELEASE_VERSION)' == ''">$([System.DateTime]::UtcNow.ToString(`yyyyMMdd-HHmm`))</VersionSuffix>

The conditions above are set up such that, if the environment variable RELEASE_VERSION is empty, the normal prefix and suffix tags are used. But if it's not empty, then the signular version tag is used instead.

Solution 4:[4]

To answer your question straight: The new SDK for msbuild is auto generating an assembly info file. You can suppress that using msbuild directives (to see the it by sample: invoke dotnet migrate on a project.json based project).

But let me tell you my handling: I had multiple projects sharing the same version. I added a version.props file which contained a property group including a item named VersionPrefix. This file I included via the csproj file (Include statement). I also removed all AssemblyInfo.cs files and let the SDK generate them for me.

I modify the version.props file during build.

Solution 5:[5]

MsBuild 2017 will generate some assembly info if you missing them in Project file.

If you can read the msbuild target file you can look at:

[VS Install Dir] \MSBuild\Sdks\Microsoft.NET.Sdk\build\Microsoft.NET.GenerateAssemblyInfo.targets

You will see you can use some property in you project file to disable generated assembly info to prevent duplicated with your generated tools.

  • <GenerateAssemblyInfo> (This property will on/off all generate assembly info)
  • <GenerateAssemblyCompanyAttribute>
  • <GenerateAssemblyConfigurationAttribute>
  • <GenerateAssemblyCopyrightAttribute>
  • <GenerateAssemblyDescriptionAttribute>
  • <GenerateAssemblyFileVersionAttribute>
  • <GenerateAssemblyInformationalVersionAttribute>
  • <GenerateAssemblyProductAttribute>
  • <GenerateAssemblyTitleAttribute>
  • <GenerateAssemblyVersionAttribute>
  • <GenerateNeutralResourcesLanguageAttribute>

Solution 6:[6]

What I do is this in .csproj

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <Deterministic>false</Deterministic>
    <AssemblyVersion>2.0.*</AssemblyVersion>
  </PropertyGroup>
</Project>

Specify the wildcard in AssemblyVersion and then turn off Deterministic flag. Numbers will be added for the wildcard.

Solution 7:[7]

I use Jenkins + Octopus for CI, and following worked quite well:

  1. Have a pre-build Powershell script that can take CI build number as a param or default to something preset.
  2. Have a separate nuspec file in the project for CI.
  3. The pre-build script would update nuspec file with the latest build version.
  4. Publish project with Jenkins.
  5. Call Nuget manually with a nuspec file from #2.
  6. Push the nuget package to Octopus.

Solution 8:[8]

As I've answered here, I've made a CLI tool called dotnet-setversion which you can use for versioning *.csproj-style .NET Core projects.

During a CI build, you can use GitVersion or another tool to determine a version number for your project and then invoke dotnet-setversion $YOUR_VERSION_STRING in your project root directory.

Solution 9:[9]

Passing /p:PropertyName=Value as arguments does not work for me (ASP.Net Core 2.0 Web App). I found the Manifest Versioning Build Tasks on marketpace: https://marketplace.visualstudio.com/items?itemName=richardfennellBM.BM-VSTS-Versioning-Task

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Chris McKenzie
Solution 2
Solution 3 Pang
Solution 4 Thomas
Solution 5 Anh Phan Tuan
Solution 6 Pang
Solution 7 Ignas
Solution 8 Community
Solution 9 Michael Giger