TFS Build 2010生成构建之 dll、exe文件的版本
TFS Build 2010的生成服务十分的强大,以前的版本号插件现在已经不需要了,直接在生成定义里面做就可以了(参考"TFS 2010 Build中,版本号的定义",具体版本号定义可参考 "软件项目版本号的命名规则及格式介绍(转)")。但是这个方法只能让生成的名称有版本号,如TestInstaller_2.0.21023.1。生成完成后的DLL文件和EXE文件的版本怎样能和这个定义的版本号匹配呢?下面就是我的方法。原创且成功实现,但是一定绕弯了,希望大家能够指正。
PS:有一款生成的插件应该能达到这个效果。不过我没成功,可能因为我的TFS是中文,插件是英文导致的。
1 实现原理
DLL和EXE文件的版本都是在Properties文件夹的AssemblyInfo.cs文件下定义的。只要在构建之前将这个文件内的版本相关信息修改,在编译后就可以实现dll的版本号了。
因此,我们大概的流程就是在生成的过程中加入一个环节----生成服务器在完确定版本号、获取源码后对所有的AssemblyInfo.cs文件进行修改,将其版本号修改后再进行生成即可。
2 版本号的确定
首先要规定一下版本号的样式。一般来说我们使用
"产品_主版本.次版本.内部版本号.修订号"的方式。因此我们再生成定义中,内部版本号脚本使用此格式
$(BuildDefinitionName)_1.0.1$(Date:MMdd)$(Rev:.r)
这里要说明一下。
-
$(BuildDefinitionName) 这个是生成版本的名称。后面用下杠连接版本。
-
1.0这个是主版本.次版本。由于升级幅度这里不会很频繁,因此采用手工修改
-
1$(Date:MMdd)这个是内部版本号。本来可以用年月日的。但是经测试,AssemblyInfo这个文件被编译的时候版本号不能使用如20110520这样的版本,而只能使用10520这样的。因此我手动将其修改为一,至少2011年可以了。
-
$(Rev:.r)每次生成的版本,自增1.
问题:内部版本号不能在生成定义的时候做计算,如mod,直接使用完整的年月日编译的时候又会出问题。因此只能手工定义。这里如果有人知道如何简单完成。请告知。谢谢!
3 修改文件内容的插件制作
由于没找到相应的方法,我只能调用外部程序,对AssemblyInfo文件进行修改。大概方式就是读取AssemblyInfo文件,正则找到相应位置,将版本号修改为传入的版本号,保存文件。
-
新建一个C#的控制台程序ModifyVersionInfo
-
定义三个参数string FilePath = args[0].ToString();//接收文件地址
string AssemblyVersion = args[1].ToString();
string AssemblyFileVersion = args[2].ToString();
-
去掉只读属性(必须,获取的源码皆为只读)File.SetAttributes(FilePath,FileAttributes.Normal);
-
读取文件FileStream fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read);
StreamReader SR = new StreamReader(fs, System.Text.Encoding.Default);
SR.BaseStream.Seek(0, SeekOrigin.Begin);
string strLine = SR.ReadToEnd();
SR.Close();
fs.Close();
-
修改文件string OutputFile;
//替换AssemblyVersion
OutputFile = Regex.Replace(strLine, "\\[assembly: AssemblyVersion.*?\\]", "[assembly: AssemblyVersion(\"" + AssemblyVersion + "\")]", RegexOptions.IgnoreCase);
//替换AssemblyFileVersion
OutputFile = Regex.Replace(OutputFile, "\\[assembly: AssemblyFileVersion.*?\\]", "[assembly: AssemblyFileVersion(\"" + AssemblyFileVersion + "\")]", RegexOptions.IgnoreCase);
-
重写文件FileStream fs2 = new FileStream(FilePath, FileMode.Create, FileAccess.Write);
StreamWriter SW = new StreamWriter(fs2, System.Text.Encoding.Default);
SW.Flush();
SW.WriteLine(OutputFile);
SW.Close();
fs2.Close();
这样,我们再执行一个修改的时候的方式是
ModifyVersionInfo.exe x:\ AssemblyInfo.cs 2.0.1520.1 2.0.1520.1
附源代码:
4 修改生成流程
4.1 查找AssemblyInfo文件
编辑"DefaultTemplate.xaml"文件,双击"RunOnAgent"过程。点击变量,新建一个变量"AllAssemblyInfoFiles",其类型为"IEnumerable<String>"用于存储AssemblyInfo文件路径列表。
在If CreatLabel过程后拖入一个"FindMatchingFiles"并改名为"FindAssemblyInfoFiles"
编辑MatchingPattern如下
Sting.Format(SourcesDirectory + "\**\assemblyinfo.cs")
编辑Result如下
AllAssemblyInfoFiles
4.2 修改文件
在FindAssemblyInfoFiles的后面拖入一个ForEach的循环。将其Values改为"AllAssemblyInfoFiles"
双击进入ForEach循环,在其中放入一个"Sequence",并取名为"ModifyAssemblyInfoFile"
双击进入ModifyAssemblyInfoFile。放入一个"InvokeProcess"取名为"ModifyAssemblyInfoFile"
修改Argument为:
String.Format(item.ToString() + " " + BuildDetail.BuildNumber.Substring(BuildDetail.BuildNumber.IndexOf("_") + 1, BuildDetail.BuildNumber.Length - BuildDetail.BuildNumber.IndexOf("_") - 1) + " " + BuildDetail.BuildNumber.Substring(BuildDetail.BuildNumber.IndexOf("_") + 1, BuildDetail.BuildNumber.Length - BuildDetail.BuildNumber.IndexOf("_") - 1))
FileName为(插件的放置位置—在生成服务器上):
String.Format("c:\ModifyVersionInfo.exe")
保存即可
5 生成测试
生成后可以看到版本号已被修改