zoukankan      html  css  js  c++  java
  • .Net项目版本号的生成

    给.Net项目编译的程序集加入版本号的方式有许多种,包括:

    1. 默认的方式,在每个项目的AssemblyInfo.cs文件中指定版本号:

     1 // Version information for an assembly consists of the following four values:
     2 //
     3 //      Major Version
     4 //      Minor Version 
     5 //      Build Number
     6 //      Revision
     7 //
     8 // You can specify all the values or you can default the Build and Revision Numbers 
     9 // by using the '*' as shown below:
    10 // [assembly: AssemblyVersion("1.0.*")]
    11 [assembly: AssemblyVersion("1.0.0.0")]
    12 [assembly: AssemblyFileVersion("1.0.0.0")]

    2. 使用IDE的插件方式定制版本号增加的方式:

    从上图中可以看到,这个插件可以通过根据时间信息来生产每一位的版本号

    3. 通过T4模板在每次编译解决方案时更新项目的版本号

    T4模板是一种在设计阶段帮助开发人员按照一定规则生产代码的机制,在IDE中可以添加:

    具体的介绍可以参考MSDN上面的:
    http://msdn.microsoft.com/en-us/library/bb126445(v=VS.100).aspx

    我们在这里使用T4模板的目的就是让它根据当前的subversion上的revision number生产版本号

    using System.Reflection;
     
    [assembly: AssemblyVersion("1.0.0.7162")]
    [assembly: AssemblyFileVersion("1.0.0.7162")]
    

    其中最后一位是当前的SvnRevisionNumber

    具体操作方法如下:

    (1)为了使用T4模板,需要安装Visual Studio 2010 SP1 SDK和Visual Studio 2010 SP1 Visualization and Modeling SDK

    Visual Studio 2010 SP1 SDK的下载地址:
    http://visualstudiogallery.msdn.microsoft.com/25622469-19d8-4959-8e5c-4025d1c9183d

    Visual Studio 2010 SP1 Visualization and Modeling SDK的下载地址:
    http://www.microsoft.com/en-us/download/details.aspx?id=23025

    (2)在需要共享同一个版本号的解决方案中新增一个新的项目

    (3)编辑这个项目文件,加入如下内容:

    (4)在这个新项目中添加一个T4模板文件

    (5)编辑这个扩展名为tt的模板, 内容如下:

     1 <#@ template hostspecific="true" language="C#" #>
     2 <#@ output extension=".cs" #>
     3 <#@ Assembly name="E:	runksrcBuildVersionSSvnEx-1.7002.1998SharpSvnSharpSvn.dll" #>
     4 <#@ import namespace="System.IO" #>
     5 <#@ import namespace="SharpSvn" #>
     6 <#
     7     string RevisionNumber = String.Empty;
     8     SvnInfoEventArgs args;
     9     SvnPathTarget target = SvnPathTarget.FromString(@"E:	runksrc");
    10     try
    11     {
    12         new SvnClient().GetInfo(target, out args);
    13         RevisionNumber = args.LastChangeRevision.ToString();
    14     }
    15     catch (SvnWorkingCopyPathNotFoundException)
    16     {
    17         RevisionNumber = "0";
    18     }
    19 #>
    20 // 
    21 // This code was generated by a tool. Any changes made manually will be lost
    22 // the next time this code is regenerated.
    23 // 
    24  
    25 using System.Reflection;
    26  
    27 [assembly: AssemblyVersion("1.0.0.<#= RevisionNumber #>")]
    28 [assembly: AssemblyFileVersion("1.0.0.<#= RevisionNumber #>")]

    上面的代码使用SharpSvn类库来读取指定目录下的svn信息,并将LastChangeRevision作为最后一位的版本号。


    注:
    这里的<#@ Assembly name="E: runksrcBuildVersionSSvnEx-1.7002.1998SharpSvnSharpSvn.dll" #>
    引用外部dll时,T4模板不能使用相对路径

    可以使用如下5中方式指定程序集的引用:

    a. 将T4需要引用的模板加入到GAC中,之后在T4中就可以直接写上程序集的名字了:
    <#@ Assembly name="SharpSvn.dll" #>

    b. 使用绝对路径指定程序集名字:
    <#@ Assembly name="E: runksrcBuildVersionSSvnEx-1.7002.1998SharpSvnSharpSvn.dll" #>

    c. 将程序集拷贝到Visual Studio的 "Public Assemblies Folder"中,之后在T4中就可以直接写上程序集的名字了:
    <#@ Assembly name="SharpSvn.dll" #>

    d. 使用一个环境变量来代替绝对路径:
    <#@ Assembly name="%mylib%SharpSvn.dll" #>

    e. 使用Visual Studio Macro来构建程序集路径:
    <#@ Assembly name="$(SolutionDir)libSharpSvn.dll" #>

    (6)编译这个包含T4模板的项目,或者保存这个模板文件,都会触发T4生成一个cs文件,内容如下:

    (7)在其他项目中添加这个生成的cs文件,以link的方式添加:

    (8)注释掉这些项目原有的版本信息:

    到此为止,所有引用了这个BuildVersion.cs文件的项目都会根据这个文件的内容生产版本号了,而这个版本号是来自于指定svn路径下的revision number。

    4. 通过定制一个MSBuild Task,在每次编译时更新版本号信息。
    MSBuild提供对复杂编译任务的可定制,我们通过继承代表一次编译任务的Task类,并重写其Execute方法来定制自己的编译任务。

    (1)首先,我们需要建立一个Class Library类型的项目,并引用下面的程序集:

    (2)继承Task类,并实现自己的Execute方法:

    下面的代码通过读取含有版本号信息的cs文件,使用正则表达式解析出四位版本号,并实现我们自己的版本号增加逻辑,这里的逻辑是根据Jenkins的环境变量,将版本号第三位置为Jenkins的BuildNumber,将第四位置为SVN Revison号。
    注:这里在处理来自svn的revision number时,当其大于UInt16.MaxValue时,我们舍弃其最高位,因为Assembly Version的值需要在0~UInt16.MaxValue之间。

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using Microsoft.Build.Utilities;
      6 using System.IO;
      7 using System.Text.RegularExpressions;
      8  
      9 namespace VersionInfoBuildTask
     10 {
     11     public class AutoIncrementTask : Task
     12     {
     13         private const string AssemlyVersionPattern =
     14         @"[assembly: AssemblyVersion(""(d{1}).(d{1}).(d{1,}).(d{1,})"")]";
     15  
     16         private const string AssemlyFileVersionPattern =
     17         @"[assembly: AssemblyFileVersion(""(d{1}).(d{1}).(d{1,}).(d{1,})"")]";
     18  
     19         private const string AssemblyInformationalVersionPattern =
     20         @"[assembly: AssemblyInformationalVersion(""(d{1}).(d{1}).(d{1,}).(d{1,})"")]";
     21  
     22         public string AssemblyInfoPath { get; set; }
     23  
     24         public override bool Execute()
     25         {
     26             try
     27             {
     28                 if (String.IsNullOrEmpty(AssemblyInfoPath))
     29                     throw new ArgumentException("AssemblyInfoPath must have a value");
     30  
     31                 string[] content = File.ReadAllLines(AssemblyInfoPath, Encoding.Default);
     32                 var rxForAssemlyVersion = new Regex(AssemlyVersionPattern);
     33                 var rxForFileVersion = new Regex(AssemlyFileVersionPattern);
     34                 var rxForInfoVersion = new Regex(AssemblyInformationalVersionPattern);
     35  
     36                 var newContent = new List<string>();
     37                 content.ToList().ForEach(line =>
     38                 {
     39                     if (rxForAssemlyVersion.IsMatch(line))
     40                     {
     41                         line = VersionMatcherForAssemlyVersion(rxForAssemlyVersion.Match(line));
     42                         Console.Out.WriteLine("Match result for assembly version is: " + line);
     43                     }
     44                     else if (rxForFileVersion.IsMatch(line))
     45                     {
     46                         line = VersionMatcherForFileVersion(rxForFileVersion.Match(line));
     47                         Console.Out.WriteLine("Match result for file version is: " + line);
     48                     }
     49                     else if (rxForInfoVersion.IsMatch(line))
     50                     {
     51                         line = VersionMatcherForInfoVersion(rxForInfoVersion.Match(line));
     52                         Console.Out.WriteLine("Match result for info version is: " + line);
     53                     }
     54                     else
     55                     {
     56                         Console.Out.WriteLine(line + " didn't match!!");
     57                     }
     58                     newContent.Add(line);
     59                 });
     60  
     61                 File.WriteAllLines(AssemblyInfoPath, newContent.ToArray());
     62             }
     63             catch (Exception ex)
     64             {
     65                 Console.Out.WriteLine(ex);
     66                 return false;
     67             }
     68  
     69             return true;
     70         }
     71  
     72         private string VersionMatcherForFileVersion(Match match)
     73         {
     74             int major = int.Parse(match.Groups[1].Value);
     75             int minor = int.Parse(match.Groups[2].Value);
     76             int build = int.Parse(match.Groups[3].Value);
     77             string revision = match.Groups[4].Value;
     78  
     79             Console.WriteLine("AutoIncrement Assembly {0}",
     80                 Path.GetFileName(AssemblyInfoPath));
     81             Console.WriteLine("Current matched version: {0}.{1}.{2}.{3}",
     82                 major, minor, build, revision);
     83  
     84             string buildNumber = Environment.GetEnvironmentVariable("BUILD_NUMBER");
     85             if (buildNumber == null) buildNumber = "0";
     86  
     87             string revisionNumber = Environment.GetEnvironmentVariable("SVN_REVISION");
     88             if (revisionNumber == null) revisionNumber = "0";
     89             if (long.Parse(revisionNumber) > UInt16.MaxValue)
     90             {
     91                 Console.WriteLine("The revision number is too big");
     92                 long rev = long.Parse(revisionNumber);
     93                 rev = rev % 10000;
     94                 revisionNumber = rev.ToString();
     95             }
     96  
     97             Console.WriteLine("Incremented to version: {0}.{1}.{2}.{3}",
     98                 major, minor, build, revision);
     99  
    100             string result = match.Result
    101                 ("[assembly: AssemblyFileVersion("$1.$2.{0}.{1}")]");
    102             return String.Format(result, buildNumber, revisionNumber);
    103         }
    104     }
    105 }

    (3)准备一个proj文件,这个文件是运行msbuild时需要指定的,主要是告知msbuild实现定制任务的程序集在哪里,和定制任务的输入文件在哪里:

    1 <?xml version="1.0" encoding="utf-8" ?>
    2 <Project ToolsVersion="4.0" DefaultTargets="IncrementBuild" 
    3     xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    4     <UsingTask AssemblyFile="VersionInfoBuildTask.dll" TaskName="AutoIncrementTask" />
    5     <Target Name="IncrementBuild">
    6         <AutoIncrementTask AssemblyInfoPath="SharedAssemblyInfo.cs" />
    7     </Target>
    8 </Project>

    (4)准备一个包含程序集版本信息的文件,这里的SharedAssemblyInfo.cs就是将要传给定制来任务处理的文件,内容如下:

    (5)将SharedAssemblyInfo.cs文件加入到解决方案中,其中的所有项目都使用Add as link方式加入这个文件,以达到共享版本信息的目的 :

    (6)将编译好的VersionInfoBuildTask.dll文件,与这个proj文件都放到Jenkins的workspace目录中:

    并使用下面的命令来运行这个定制的Task:
    msbuild BuildTask.proj /t:IncrementBuild

    运行之后,查看SharedAssemblyInfo.cs的内容,发现版本号已经发生了改变:

    好了,下面就可以使用msbuild来编译整个解决方案了,之后我们查看编译出来的程序集的版本号:

    版本号最后两位对应Jenkins上的build number和revision number(舍去最高位),这样做是方便查询每个版本所对应的代码变更信息:

  • 相关阅读:
    一个word小技巧
    Android 自定义组件之 带有悬浮header的listview
    传智播客 java基础 相关资料 Day2
    js取整 摘抄
    ifram子页面父页面相互调用
    寻知图项目收获--项目管理方面
    圣经学习 读经群读经记录(一)申命记5-7章
    java1234教程系列笔记 S1 Java SE chapter 02 写乘法口诀表
    java1234教程系列笔记 S1 Java SE chapter 02 lesson 03 java基本数据类型
    java1234教程系列笔记 S1 Java SE 02 eclipse初步使用、注释、标识符
  • 原文地址:https://www.cnblogs.com/liupengblog/p/4648927.html
Copyright © 2011-2022 走看看