一、版本概述
通常情况下,我们每个项目的版本号,都是维护在AssemblyInfo.cs 文件中;
[assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.5.10309")]
分别对应着生成后.dll或者.exe文件属性中的产品版本和文件版本:
二、场景描述
但是我们一个解决方案可能会有几十甚至上百个工程文件,我们每次发版都去修改每个工程文件的AssemblyInfo.cs文件,这是比较大的工作量。 有兄弟可能要说了,我写个工具批量改不就得了,的确也有类似的工具。
一般正式的产品发布都是一套持续集成来着,就需要一个单独的文件来控制版本,这样修改起来更方便了;
三、解决方案
(1)在解决方案的所有工程文件(.csproj文件用notepad++之类文本编辑器打开)引入以下:
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="..\msbuild\BuildCommon.targets" />
注意:放在<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> 这个后面
(2)在解决方案加 msbuild\BuildCommon.targets文件(包含文件夹),BuildCommon.targets的内容如下:
<?xml version="1.0" encoding="utf-8"?> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <!-- Below snippets go here --> <PropertyGroup> <VersionAssembly>3.8.9.2</VersionAssembly> <CompileDependsOn> CommonBuildDefineModifiedAssemblyVersion; $(CompileDependsOn); </CompileDependsOn> </PropertyGroup> <UsingTask TaskName="RegexUpdateFile" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll"> <ParameterGroup> <Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" /> <Regex ParameterType="System.String" Required="true" /> <ReplacementText ParameterType="System.String" Required="true" /> </ParameterGroup> <Task> <Reference Include="System.Core" /> <Using Namespace="System" /> <Using Namespace="System.IO" /> <Using Namespace="System.Text.RegularExpressions" /> <Using Namespace="Microsoft.Build.Framework" /> <Using Namespace="Microsoft.Build.Utilities" /> <Code Type="Fragment" Language="cs"> <![CDATA[ try { var rx = new System.Text.RegularExpressions.Regex(this.Regex); for (int i = 0; i < Files.Length; ++i) { var path = Files[i].GetMetadata("FullPath"); if (!File.Exists(path)) continue; var txt = File.ReadAllText(path); txt = rx.Replace(txt, this.ReplacementText); File.WriteAllText(path, txt); } return true; } catch (Exception ex) { Log.LogErrorFromException(ex); return false; } ]]> </Code> </Task> </UsingTask> <Target Name="CommonBuildDefineModifiedAssemblyVersion" Condition="'$(VersionAssembly)' != ''"> <!-- Find AssemblyInfo.cs or AssemblyInfo.vb in the "Compile" Items. Remove it from "Compile" Items because we will use a modified version instead. --> <ItemGroup> <OriginalAssemblyInfo Include="@(Compile)" Condition="%(Filename) == 'AssemblyInfo' And (%(Extension) == '.vb' Or %(Extension) == '.cs')" /> <Compile Remove="**/AssemblyInfo.vb" /> <Compile Remove="**/AssemblyInfo.cs" /> </ItemGroup> <!-- Copy the original AssemblyInfo.cs/.vb to obj\ folder, i.e. $(IntermediateOutputPath). The copied filepath is saved into @(ModifiedAssemblyInfo) Item. --> <Copy SourceFiles="@(OriginalAssemblyInfo)" DestinationFiles="@(OriginalAssemblyInfo->'$(IntermediateOutputPath)%(Identity)')"> <Output TaskParameter="DestinationFiles" ItemName="ModifiedAssemblyInfo"/> </Copy> <!-- Replace the version bit (in AssemblyVersion and AssemblyFileVersion attributes) using regular expression. Use the defined property: $(VersionAssembly). --> <Message Text="Setting AssemblyVersion to $(VersionAssembly)" /> <RegexUpdateFile Files="@(ModifiedAssemblyInfo)" Regex="Version\("(\d+)\.(\d+)(\.(\d+)\.(\d+)|\.*)"\)" ReplacementText="Version("$(VersionAssembly)")" /> <!-- Include the modified AssemblyInfo.cs/.vb file in "Compile" items (instead of the original). --> <ItemGroup> <Compile Include="@(ModifiedAssemblyInfo)" /> </ItemGroup> </Target> </Project>
(3)生成解决方案,所有的工程生成文件的属性都如下:
这个版本号就是