We can define versions on our .NET Core applications, but how to get the version at runtime? There are several ways to do it.
First, let's look at a typical .NET Core project file with versioning. We can define the version numbers for AssemblyVersion, FileVersion and Version in the project file (.csproj).
The AssemblyVersion and FileVersion attributes must be in format of "major[.minor[.build[.revision]]]" or you will get a compile time error (CS7034).
The attribute Version can contain customized strings, like a surfix of "-xyz" as shown below:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<AssemblyVersion>1.1.1.1</AssemblyVersion>
<FileVersion>2.2.2.2</FileVersion>
<Version>3.3.3.3-xyz</Version>
</PropertyGroup>
</Project>
In compile time, this will generate a class file:
//------------------------------------------------------------------------------
// <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("netcoreappver")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("2.2.2.2")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("3.3.3.3-xyz")]
[assembly: System.Reflection.AssemblyProductAttribute("netcoreappver")]
[assembly: System.Reflection.AssemblyTitleAttribute("netcoreappver")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.1.1.1")]
// Generated by the MSBuild WriteCodeFragment class.
With this in mind, let's see how we can read these values in runtime.
AssemblyVersion
There are two ways to get the AssemblyVersion
If you are not getting this in a static method, you can use
GetType().Assembly.GetName().Version.ToString()
But if you need to use this in a static method, you may have to create a class like this:
class Foo
{
public string GetAssemblyVersion()
{
return GetType().Assembly.GetName().Version.ToString();
}
}
and then:
new Foo().GetAssemblyVersion()
This is ugly code. So we have another way to read the AssemblyVersion
Assembly.GetEntryAssembly().GetName().Version
This can be used in static and non-static methods.
Both two methods will return 1.1.1.1
FileVersion
We can use GetCustomAttribute extension method to get the AssemblyFileVersionAttribute and read the Version attribute.
Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>().Version
It will return 2.2.2.2
Version
Like FileVersion but this time we will use AssemblyInformationalVersionAttribute
Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion
It will return 3.3.3.3
Complete Sample Code
using System;
using System.Reflection;
namespace netcoreappver
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine($"GetType().Assembly.GetName().Version: " +
$"{new Foo().GetAssemblyVersion()}");
Console.WriteLine($"Assembly.GetEntryAssembly().GetName().Version: " +
$"{Assembly.GetEntryAssembly().GetName().Version}");
Console.WriteLine($"Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>().Version:" +
$"{Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>().Version}");
Console.WriteLine($"Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion:" +
$"{Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute> ().InformationalVersion}");
Console.ReadKey();
}
}
class Foo
{
public string GetAssemblyVersion()
{
return GetType().Assembly.GetName().Version.ToString();
}
}
}
Which version should I use?
According to this thread:
AssemblyVersion
Where other assemblies that reference your assembly will look. If this number changes, other assemblies must update their references to your assembly.
AssemblyFileVersion
Used for deployment. You can increase this number for every deployment. It is used for setup programs. Use it to mark assemblies that have the same AssemblyVersion, but are generated from different builds.
In Windows, it can be viewed in the file properties.
If possible, let it be generated by MSBuild. The AssemblyFileVersion is optional. If not given, the AssemblyVersion is used.
I use the format: major.minor.revision.build, where I use revision for development stage (Alpha, Beta, RC, and RTM), service packs and hot fixes.
AssemblyInformationalVersion
The Product version of the assembly. This is the version you would use when talking to customers or for display on your website. This version can be a string, like '1.0 Release Candidate'.
Zane
Thank you good sir!
Dave Dumaresq
Thanks for this!
I'm getting n exception of type 'System.NullReferenceException' when I try to get GetCustomAttributes such as AssemblyInformationalVersionAttribute. Any ideas why or work-arounds?
.NET Core SDK (reflecting any global.json): Version: 2.1.803
Ian
Very useful post! Thank you.
Iván Sainz (tecDev PRO)
Good one!
MateuszO
Hello, did you know how to place DateTime.Now in: <PropertyGroup> <Version>"----------"</Version> </PropertyGroup>
I want to know the creation date of the version
PHenry
Can you please show how to load the description and copyright fields please? I can't seem to figure it out.
Kit
Note that from .NET8, you have to include this to prevent your informational version having a weird suffix.
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
Yes, it is indeed an odd, breaking change in .NET 8.
Fredy
I am not sure why i still get this
1.0.0.0+38d05bcfe2cbd3b1bf3eee7450200b5a4edd6897
instead of1.0.1.0
. I'm using Asp.net Core with net8. Do you have any idea?