C#

C#版本号自动增加与自定义版本号

AssemblyInfo,Version

Updated on April 17, 2022 Posted by elmagnifico on April 17, 2022

Foreword

之前写过一篇,C++ CLI/CLR下的版本号自增,最近又探索了一下,发现了一些新的方式,也比较简单方便。

http://elmagnifico.tech/2021/06/01/CLR-Auto-Version-Increase/

TextTemplate

TextTemplate的语法教程相关,看官方文档

https://docs.microsoft.com/en-us/visualstudio/modeling/writing-a-t4-text-template?view=vs-2022

简单说在C#工程中增加一个文本模板,后缀是tt的文件

image-20220417145844662

然后输入下面的内容

<#@ template language="C#" #>
// 
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.
// 

using System.Reflection;

[assembly: AssemblyVersion("1.0.1.<#= this.RevisionNumber #>")]
[assembly: AssemblyFileVersion("1.0.1.<#= this.RevisionNumber #>")]
<#+
    int RevisionNumber = (int)(DateTime.UtcNow - new DateTime(2010,1,1)).TotalDays;
#>

大致解释一下,文件模板,就是当你任何修改保存或者编译的时候,工程会自动执行文件模板。上述的模板就会生成一个C#的同名.cs文件,这个文件在tt模板的下面,其内容其实就是一个标准的cs的文件,只是RevisionNumber的值,每次会自动计算更新并存入文件中。

这样版本号的末尾就变成了utc时间距2010年1月1日所经过的日子了

通过这种方式就巧妙的实现了AssemblyVersionAssemblyFileVersion的自动更新,并且规则可以自己定义

  • 版本号的模式必须是x.x.x.x,否则系统会自动给你补0上去

下面这个模板则是自动生成1.年.1月日.1十分格式的版本号

<#@ template language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>

//
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.
//

using System.Reflection;

<#
    var date = DateTime.Now;
    int major = 1;
    int minor = date.Year;
    int build = 10000 + int.Parse(date.ToString("MMdd"));
    int revision = 10000 + int.Parse(date.ToString("HHmm"));
#>

[assembly: AssemblyVersion("<#= $"{major}.{minor}.{build}.{revision}" #>")]
[assembly: AssemblyFileVersion("<#= $"{major}.{minor}.{build}.{revision}" #>")]

这个模板稍微特殊一点,他是通过反向读取cs中的内容,来进行更新的,当然这里不会死锁。

<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#
    string output = File.ReadAllText(this.Host.ResolvePath("AssemblyInfo.cs"));
    Regex pattern = new Regex("AssemblyVersion\\(\"(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<revision>\\d+)\\.(?<build>\\d+)\"\\)");
    MatchCollection matches = pattern.Matches(output);
    if( matches.Count == 1 )
    {
        major = Convert.ToInt32(matches[0].Groups["major"].Value);
        minor = Convert.ToInt32(matches[0].Groups["minor"].Value);
        build = Convert.ToInt32(matches[0].Groups["build"].Value) + 1;
        revision = Convert.ToInt32(matches[0].Groups["revision"].Value);
        if( this.Host.ResolveParameterValue("-","-","BuildConfiguration") == "Release" )
            revision++;
    }
#>

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Resources;

// General Information
[assembly: AssemblyTitle("DCTracker")]
[assembly: AssemblyDescription("Diablo Clone Tracker")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("elmagnifico")]
[assembly: AssemblyProduct("DCTracker")]
[assembly: AssemblyCopyright("opyright ©  2022")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Version Information
[assembly: AssemblyVersion("<#= this.major #>.<#= this.minor #>.<#= this.revision #>.<#= this.build #>")]
[assembly: AssemblyFileVersion("<#= this.major #>.<#= this.minor #>.<#= this.revision #>.<#= this.build #>")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]

<#+
    int major = 1;
    int minor = 0;
    int revision = 0;
    int build = 0;
#>
  • 需要注意这个模板的major、minor、revision的修改,需要修改对应的cs,而build是自动的,其他模板修改可能是直接修改tt文件就行了

他生成的模板就像下面一样

image-20220417150856079


using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Resources;

// General Information
[assembly: AssemblyTitle("DCTracker")]
[assembly: AssemblyDescription("Diablo Clone Tracker")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("elmagnifico")]
[assembly: AssemblyProduct("DCTracker")]
[assembly: AssemblyCopyright("opyright ©  2022")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Version Information
[assembly: AssemblyVersion("1.2.1.20")]
[assembly: AssemblyFileVersion("1.2.1.20")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]

Summary

VS的版本号的设计着实有些死板,想自己定义成自己想要的方式都不行,也太蠢了

Textemplate的模式,不限于C#,只要是MSbuild其实都可以使用,他是在编译过程中作为一个辅助工具一样的,被调用而已,所以C++或者是其他的工程只要在VS里基本都可以使用。

Quote

https://stackoverflow.com/questions/356543/can-i-automatically-increment-the-file-build-version-when-using-visual-studio

https://stackoverflow.com/questions/826777/how-to-have-an-auto-incrementing-version-number-visual-studio

http://www.cppblog.com/diryboy/archive/2010/08/17/VS2010AddT4InCppProject.html

https://docs.microsoft.com/en-us/visualstudio/modeling/design-time-code-generation-by-using-t4-text-templates?view=vs-2022

https://docs.microsoft.com/en-us/visualstudio/modeling/code-generation-and-t4-text-templates?view=vs-2022