Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / .NET / .NET-Standard

.NET Core/Standard Auto Incrementing Versioning

5.00/5 (4 votes)
23 Feb 2020CPOL2 min read 12.2K  
How to get nice auto incrementing assembly versions inside your .NET Core/Standard projects
This post shows how to using the AutoGenerated .NET Core/Standard AssemblyInfo.cs, and also shows how to opt out of the Auto Assembly Info Generation Process and use our own auto increment scheme.

Using the AutoGenerated .NET Core/Standard AssemblyInfo.cs

When you create a new .NET Core/.NET Standard project, you will get a auto generated set of attributes, which is based on these settings for the project.

Which you can in effect in the obj folder, where an auto generated xxxxAssemblyInfo.cs class is created for you.

C#
/------------------------------------------------------------------------------
// <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("SomeDemoCode.Std")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
[assembly: System.Reflection.AssemblyProductAttribute("SomeDemoCode.Std")]
[assembly: System.Reflection.AssemblyTitleAttribute("SomeDemoCode.Std")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

// Generated by the MSBuild WriteCodeFragment class.

So when we build the project, we would end up with this version being applied to the resulting output for the project.

Ok, that explains how the AssemblyInfo stuff works in .NET Core/Standard, but what is the .NET Cote/Standard way of doing auto incrementing versions?

Well, believe it or not, there is not a native feature for this, there are various efforts/attempts at this which you can read more about:

After reading all of those, the best approach seemed to be based upon sticking with using the Auto generated Assembly.info stuff, but to come up with some scheme that would aid in the generation of the assembly version at build time.

What that means is you want to ensure your .csproj file looks something like this, where it can be seen that some of the .NET Core/Standard auto generated AssemblyInfo stuff is made available directly in the project file:

XML
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
  <TargetFramework>netstandard2.0</TargetFramework>
  <Platforms>x64</Platforms>
</PropertyGroup>

<PropertyGroup>
  <DefineConstants>STD</DefineConstants>
  <PlatformTarget>x64</PlatformTarget>
  <AssemblyName>SomeDemoCode.Std</AssemblyName>
  <RootNamespace>SomeDemoCode.Std</RootNamespace>
  <VersionSuffix>1.0.0.$([System.DateTime]::UtcNow.ToString(mmff))</VersionSuffix>
  <AssemblyVersion Condition=" '$(VersionSuffix)' == '' ">0.0.0.1</AssemblyVersion>
  <AssemblyVersion Condition=" '$(VersionSuffix)' != '' ">$(VersionSuffix)</AssemblyVersion>
  <Version Condition=" '$(VersionSuffix)' == '' ">0.0.1.0</Version>
  <Version Condition=" '$(VersionSuffix)' != '' ">$(VersionSuffix)</Version>
  <Company>SAS</Company>
  <Authors>SAS</Authors>
  <Copyright>Copyright © SAS 2020</Copyright>
  <Product>Demo 1.0</Product>
</PropertyGroup>

</Project>

With this in place, you will get an auto versioned Assembly version using just .NET Core/Standard approach.

But What About InternalsVisibleTo?

Quite often, we want to still expose our .NET Standard projects to test projects. And if the .NET Core/Standard projects auto generate the AssemblyInfo based on either defaults or attributes in the actual .csproj file, how do we add a InternalsVisibleTo, this doesn’t seem to be covered by the auto generated AssemblyInfo that gets created for .NET Core/Standard project, nor does it seem to be available as a csproj level MSBUILD property item. So how do we do this?

Luckily, this is quite simple. We just need to do the following in a custom file which you can call anything you want, you can even call it “AssemblyInfo.cs” if you want.

C#
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("SomeDemoCode.IntegrationTests")]

Opting Out Of the Auto Assembly Info Generation Process and Using Our Own Auto Increment Scheme

If you want to use the .NET Framework approach to auto versioning, this is normally done with a wildcard in the

C#
[assembly: AssemblyVersion("1.0.*")]

So you might think, hmm so I can just override this by adding my own AssemblyInfo.cs. But this will not work. You will get this when you build:

> Error CS0579: Duplicate 'System.Reflection.AssemblyFileVersionAttribute' attribute
> Error CS0579: Duplicate 'System.Reflection.AssemblyInformationalVersionAttribute' attribute
> Error CS0579: Duplicate 'System.Reflection.AssemblyVersionAttribute' attribute

Luckily, we can opt out of this auto generation process, where we have to add the following to our .NET Core/.NET standard csproj file:

XML
<PropertyGroup>
  <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
  <Deterministic>false</Deterministic>
</PropertyGroup>

You need the deterministic property, otherwise you will get this error:

Wildcards are only allowed if the build is not deterministic, 
which is the default for .Net Core projects. Adding False to csproj fixes the issue.

With this in place, we can now include a custom AssemblyInfo.cs which could for example use an auto incrementing version number, where we use a wild card when specifying the AssemblyVersion.

C#
using System.Reflection;

using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SomeDemoCode.Std")]
[assembly: AssemblyDescription("SomeDemoCode .NET Standard")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("SAS")]
[assembly: AssemblyProduct("SAS 1.0")]
[assembly: AssemblyCopyright("Copyright © SAS 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("CA7543D7-0F0F-4B48-9398-2712098E9324")]
 
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.*")]

Now when you build, you will get some nice auto incrementing assembly versions inside your .NET Core/Standard projects.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)