The attribute [AssemblyVersion()]
and [AssemblyFileVersion()]
both accepts a constant string
as parameter.
So I can create a static class
with a const
string
in the current assembly, and can supply it to these attributes
as parameters as below
public static class App
{
public const string Version = "1.0.0.1";
}
and update the AssemblyInfo.cs
as
[assembly: AssemblyVersion(App.Version)]
[assembly: AssemblyFileVersion(App.Version)]
This is an alternative suggestion then the automation/trick suggested by @Kelly R and @Gravtion above.
Update 1 - Using T4
template
In case you want to go for T4 template
as @KellyR suggested the following can help you with the version:
private string Version()
{
DateTime START = new DateTime(2021,2, 14); //StartDate
DateTime NOW = DateTime.Now;
int numMonths = (int)(NOW.Subtract(START).Days / (365.25 / 12));
int Major = numMonths / 12;
int Minor = numMonths % 12;
int Build = (int)DateTime.Now.Day;
string Revision = $"{(int)DateTime.Now.Hour}{DateTime.Now.Minute}";
return $"{Major}.{Minor}.{Build}.{Revision}";
}
The START
stores the start date of the project which is used to calculate the number of months passed till now. Then it's dividing the numMonths
by 12 to get the number of year passed(considering it as Major
version) and keeps the remaining months as Minor
version then the current day as Build
and hour + Minutes as Revision
.
With that every time you build you will get the latest version of your product.
This can also be used in the T4 template
as follows:
<#@ output extension=".cs" #>
<#@ template debug="true" language="C#" hostspecific="false" #>
using System.Reflection;
[assembly: AssemblyVersion("<#= NewVersion() #>")]
[assembly: AssemblyFileVersion("<#= NewVersion() #>")]
<#+
private string NewVersion()
{
DateTime START = new DateTime(2021,2, 14); //StartDate
DateTime NOW = DateTime.Now;
int numMonths = (int)(NOW.Subtract(START).Days / (365.25 / 12));
int Major = numMonths / 12;
int Minor = numMonths % 12;
int Build = (int)DateTime.Now.Day;
string Revision = $"{(int)DateTime.Now.Hour}{DateTime.Now.Minute}";
return $"{Major}.{Minor}.{Build}.{Revision}";
}
//Started On = 12-5-2021;
#>
Just remember to comment AssemblyVersion
and AssemblyFileVersion
in AssemblyInfo.cs
when using it as T4 template
.
//[assembly: AssemblyVersion("1.0.0.0")]
//[assembly: AssemblyFileVersion("1.0.0.0")]
Update 2 - Using MsBuild to rewrite AssemblyInfo.cs
with regx
We can also change the assembly version by editing the .csproj
file by adding the following:
<Target Name="AssemblyVersion" BeforeTargets="CoreCompile" DependsOnTargets="PrepareForBuild">
<PropertyGroup>
<AssemblyInfo>Properties\AssemblyInfo.cs</AssemblyInfo>
<AssemblyInfoContent>$([System.IO.File]::ReadAllText($(AssemblyInfo)))</AssemblyInfoContent>
<VersionRegex>(\[\s*assembly\s*:\s*AssemblyVersion\(\s*"(\d+)\.(\d+)\.(\d+)(\.)(\d+)("\)\s*\]))</VersionRegex>
<BuildAndRevisionRegex>(\d+\.\d+")</BuildAndRevisionRegex>
<AssemblyVersion>$([System.Text.RegularExpressions.Regex]::Match('$(AssemblyInfoContent)', '$(VersionRegex)'))</AssemblyVersion>
<!-- New AssemblyVersion Block -->
<NowTime>$([System.DateTime]::Now.Year)</NowTime>
<MajorVersion>$([MSBuild]::Subtract($(NowTime), 2023).ToString("0"))</MajorVersion>
<MinorBuildRevision>$([System.DateTime]::Now.ToString("M.d.hhm"))</MinorBuildRevision>
<AssemblyVersion>[assembly: AssemblyVersion("$(MajorVersion).$(MinorBuildRevision)")]</AssemblyVersion>
</PropertyGroup>
<!-- Write New AssemblyVersion Block to AssemblyInfo.cs file -->
<WriteLinesToFile File="$(AssemblyInfo)" Lines="$([System.Text.RegularExpressions.Regex]::Replace($(AssemblyInfoContent), $(VersionRegex), $(AssemblyVersion)))" Overwrite="true" />
</Target>
What it does is it reads the AssemblyInfo.cs
file and replaces the AssemblyVersion
using regularexpressions
and DateTime
values.
Look for the below code where we can change the value 2023
to the any current/past year to generate the MajorVersion
.
<MajorVersion>$([MSBuild]::Subtract($(NowTime), 2023).ToString("0"))</MajorVersion>
<MinorBuildRevision>$([System.DateTime]::Now.ToString("M.d.hhm"))</MinorBuildRevision>
The MajorVersion
is calculated as DateTime.Now.Year - 2023
so expect it to be 0
if the first release year is 2023
. The Minor
,Build
& Revision
are dynamic in nature as it is derived with the DateTime
component giving the value in format "M.d.hhm"
DateTime.Now.ToString("M.d.hhm")
At the time of this update it is giving a value 8.23.0458
and with the major version it becomes 0.8.23.0458
Update 3 - creating NewVersion.cs
with AssemblyFileVersion
There is one more better way is to generate a new NewVersion.cs
with AssemblyFileVersion
attribute. Which can be achieved with WriteCodeFragment
as:
<Target Name="BeforeBuild">
<PropertyGroup>
<NowTime>$([System.DateTime]::Now.Year)</NowTime>
<MajorVersion>$([MSBuild]::Subtract($(NowTime), 2023).ToString())</MajorVersion>
<NewVersion>$(MajorVersion).$([System.DateTime]::Now.ToString("M.d.hhm"))</NewVersion>
</PropertyGroup>
<ItemGroup>
<AssemblyAttributes Include="AssemblyFileVersion">
<_Parameter1>$(NewVersion)</_Parameter1>
</AssemblyAttributes>
</ItemGroup>
<WriteCodeFragment AssemblyAttributes="@(AssemblyAttributes)"
Language="C#"
OutputDirectory="$(IntermediateOutputPath)"
OutputFile="NewVersion.cs">
<Output TaskParameter="OutputFile" ItemName="Compile" />
<Output TaskParameter="OutputFile" ItemName="FileWrites" />
</WriteCodeFragment>
</Target>
Just add the above to csproj
file at the end and comment the AssemblyFileVersion
in AssemblyInfo.cs
else the compiler will complain for duplicate attribute.
This will create a NewVersion.cs
to obj/Debug
folder and will use it for compilation and keep updating the file with a new version.