9

I know that the format of the assembly version is:

<major version>.<minor version>.<build number>.<revision>

Is there a way to make the version number the current date?

For example, if I compile the build today, the version number should look like this:

2016.02.11.xxxxx

Where xxxxx is what you normally get if you set the assembly version to 1.0.0.*.

I googled around but didn't find an answer (not even a question) for this.

Allen Zhang
  • 2,432
  • 2
  • 20
  • 31
  • 2
    Just use `x.y.*`, the build number is the number of days since 2000, the revision number is the number of seconds past midnight / 2. – Hans Passant Feb 12 '16 at 23:04

4 Answers4

5

Easy part: In Project Properties > Build Events, add a "Pre-build event command line" like this:

"D:\SomePath\MyAssemblyInfoPatcher.exe" "$(ProjectDir)Properties\AssemblyInfo.cs"

Hard part: You provide MyAssemblyInfoPatcher.exe , a program which opens the file specified by its first argument, searches it for this line (ignoring the values there):

[assembly: AssemblyVersion("8888.0.*")]

, replaces the line with one of these (or similar):

[assembly: AssemblyVersion("2016.11.05.2359")]
[assembly: AssemblyVersion("2016.1105.2359.1")]
[assembly: AssemblyVersion("8888.2016.1105.2359")]

, and rewrites the file.

The program derives these values from the system date and time according to a pattern like one of these:

yyyy.mm.dd.hhmm
yyyy.mmdd.hhmm.counter
arbitrary.yyyy.mmdd.hhmm

If you hard-code the pattern you want, your program needs no configuration. For the counter (if you chose it), the program can increment the value it finds in the file. The counter must be word (UInt16) so that incrementing 65535 wraps around to 0. If you want the counter to reset each day, now you need to store a reference date, in a side file or maybe in a comment inside AssemblyInfo.cs. For the arbitrary number, you can re-use what's in the file, or hard-code a replacement.

Time issue: Beginning and ending Daylight Savings Time make the local time occasionally jump ahead by one hour (not a problem) and fall back by one hour (always a worry). To almost-guarantee no duplicate time ranges, you can use UTC or maybe the local time except ignore Daylight Savings Time. Local time without Daylight Savings Time is a compromise used by many web servers, and even the optional automatic date-based version numbering built into VS (it overrides a.b.* with a.b.{days since Jan. 1, 2000 at 00:00}.{seconds since Jan. 1, 2000 at 00:00 divided by 2}, so it is not human readable).

Possible simplifications: •The target filename is always "AssemblyInfo.cs", so it could be specified in the program and omitted from the argument: "$(ProjectDir)Properties". •If VS executes the program with the current directory set to "D:\Users\myusername\Documents\Visual Studio 2010\Projects\solutionfolder\projectfolder\Properties", it doesn't need an argument.

•A program can read its AssemblyVersion via System.Reflection.Assembly.GetExecutingAssembly().GetName().Version .
•File:Properties displays AssemblyFileVersion.
•AssemblyFileVersion (if not specified) defaults to AssemblyVersion .

A876
  • 471
  • 5
  • 8
3

For Visual Sutdio 2022, Here's a new solution you maybe needs. it depend on modify csproj file.

How to Change AssemblyInfo.cs AssemblyVersion with date/time and increment revision daily by one in Visual Studio 2022

Copied from question:

here's solution for generate a Version with (Year, Month, Day, Incremental Daily)

This code must inserted before close of </project> tag in *.csproj file

<!-- Change AssemblyInfo.cs AssemblyVersion with date/time and increment revision daily by one in Visual Studio 2022 -->
<Target Name="AssemblyVersion" BeforeTargets="CoreCompile" DependsOnTargets="PrepareForBuild">
    <PropertyGroup>
        <!-- Define Constants -->
        <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>

        <!-- Parse Build and Revision from AssemblyInfo-->
        <AssemblyVersion>$([System.Text.RegularExpressions.Regex]::Match('$(AssemblyInfoContent)', '$(VersionRegex)'))</AssemblyVersion>
        <BuildAndRevision>$([System.Text.RegularExpressions.Regex]::Match('$(AssemblyVersion)', '$(BuildAndRevisionRegex)'))</BuildAndRevision>
        <BuildAndRevision>$(BuildAndRevision.Remove($(BuildAndRevision.LastIndexOf('"')), 1))</BuildAndRevision>
        
        <!-- Generate Build and Revision from AssemblyVersion -->
        <Build>$(BuildAndRevision.SubString(0, $(BuildAndRevision.LastIndexOf('.'))))</Build>
        <Revision>$(BuildAndRevision.SubString($([MSBuild]::Add($(BuildAndRevision.LastIndexOf('.')), 1))))</Revision>
        
        <!-- Increment Revision by one if Build equal Current Day otherwise start from one as new Day Build-->
        <Revision Condition ="$([System.DateTime]::Now.Day) == $(Build)">$([MSBuild]::Add($(Revision), 1))</Revision>
        <Revision Condition ="$([System.DateTime]::Now.Day) != $(Build)">1</Revision>

        <!-- New AssemblyVersion Block -->
        <AssemblyVersion>[assembly: AssemblyVersion("$([System.DateTime]::Now.ToString("yyyy.M.d.$(Revision)"))")]</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>

A generated result will be like that:

  1. Each day a library/project will start from (Year, Month, Day, Daily Day Incremental)

Incremental daily

  1. Next Day increment from one again: Next Day increment from one again
nickgreek
  • 181
  • 1
  • 7
2

This can be done via MSBUILD. Here is a good description for it. You don't need a build server for this. You can call your custom MSBUILD target in the BeforeBuild Target of your project. For that open your csproj file with an editor and locate this section at the end of the file:

<!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
Matthias
  • 344
  • 3
  • 8
  • The link you provided seems to be broken (?, at least today for me). But the following one works for me (in a .Net Core project) https://scottdorman.blog/2018/08/20/net-core-project-versioning/ – Stefan Wuebbe Feb 20 '22 at 19:49
1
using System;
using System.IO;
using System.Linq;

namespace MyAssemblyInfoPatcher
{
    internal class Program
    {
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {
                string path = args[0].ToString();
                Console.WriteLine(string.Format("Current App version is set to: {0}", path));
                string now_date = DateTime.Now.ToString("yyyy.MM.dd.HHmm");
                if (File.Exists(path))
                {
                    string _AssemblyVersion = string.Empty;
                    string _AssemblyFileVersion = string.Empty;

                    var lines = File.ReadLines(string.Format(path));
                    for (int i = 0; i < lines.Count(); i++)
                    {
                        if (lines.ElementAt(i).ToString().StartsWith("[assembly: AssemblyVersion"))
                        {
                            _AssemblyVersion = lines.ElementAt(i).ToString();
                        }
                        else if (lines.ElementAt(i).ToString().StartsWith("[assembly: AssemblyFileVersion"))
                        {
                            _AssemblyFileVersion = lines.ElementAt(i).ToString();
                        }
                    }

                    string _replace_assembly = File.ReadAllText(path);

                    if (_AssemblyVersion != string.Empty)
                    {
                        _replace_assembly = _replace_assembly.Replace(_AssemblyVersion, string.Format("[assembly: AssemblyVersion(\"{0}\")]", now_date));
                    }
                    if (_AssemblyFileVersion != string.Empty)
                    {
                        _replace_assembly = _replace_assembly.Replace(_AssemblyFileVersion, string.Format("[assembly: AssemblyFileVersion(\"{0}\")]", now_date));
                    }

                    File.WriteAllText(path, _replace_assembly);
                }
            }   
        }
    }
}

Above the programs code, you can create a console application and in Project Properties > Build Events, add a "Pre-build event command line" like this: "D:\SomePath\MyAssemblyInfoPatcher.exe" "$(ProjectDir)Properties\AssemblyInfo.cs"