如何使用MSBuild仅在程序集更改时更新版本信息?

8
我有一个需求,需要将多个Web安装项目(使用VS2005和ASP.Net/C#)安装到同一个虚拟文件夹中。这些项目共享一些程序集引用(文件系统都结构化使用相同的“bin”文件夹),使得部署对这些程序集的更改成为问题,因为MS安装程序只会覆盖那些已安装版本早于MSI中的版本的程序集。
我并不是在说悲观的安装方案是错误的 - 只是它在我要处理的环境中创建了一个问题。由于有大量的共同程序集和许多可能更改共同程序集但忘记更新其版本号的开发人员,尝试手动管理版本控制最终会导致在安装时产生巨大的混乱。
在此问题的反面,同样重要的是不要自行更新版本号并在每次安装时替换所有共同程序集,因为这可能(至少暂时)掩盖了实际进行更改的情况。
话虽如此,我正在寻找一种方法来仅在程序集成分(代码模块、资源等)实际更改时更新程序集版本信息(最好使用MSBuild)。
我找到了一些相关的参考资料,至少部分信息是有用的(MSDN上的AssemblyInfo任务)(看起来类似于我需要的,但已经两年多没有清晰的解决方案)
我的团队还使用TFS版本控制,因此自动化解决方案可能应该包括在构建过程中检查/签出AssebmlyInfo的方法。
任何帮助都将不胜感激。
提前致谢。
3个回答

10

由于我没有使用TFS的经验,无法回答你所有的问题。

但是,我可以建议您使用一种比使用AssemblyInfo任务更新AssemblyInfo.cs文件更好的方法。该任务似乎只是从头开始重新创建标准的AssemblyInfo文件,并且会丢失您可能添加的任何自定义部分。

因此,我建议您研究MSBuild Community Tasks项目中的FileUpdate任务。它可以查找文件中的特定内容并替换它,就像这样:

<FileUpdate 
Files="$(WebDir)\Properties\AssemblyInfo.cs"
Regex="(\d+)\.(\d+)\.(\d+)\.(\d+)"
ReplacementText="$(Major).$(ServicePack).$(Build).$(Revision)" 
Condition="'$(Configuration)' == 'Release'"
/>

您可以通过几种方式控制构建编号的递增。因为我只希望在构建完全成功时才递增构建编号,所以我使用了两步方法:

  • 从文本文件中读取一个数字(文件中唯一的内容是该数字),并将其加1而不改变文件;
  • 在构建过程的最后一步,如果一切顺利,将递增的数字保存回文本文件。

有一些任务如ReadLinesFromFile可以帮助您完成这个操作,但我发现编写一个小的自定义任务最容易:

using System;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace CredibleCustomBuildTasks
{
    public class IncrementTask : Task
    {
        [Required]
        public bool SaveChange { get; set; }

        [Required]
        public string IncrementFileName { get; set; }

        [Output]
        public int Increment { get; set; }

        public override bool Execute()
        {
            if (File.Exists(IncrementFileName))
            {
                string lines = File.ReadAllText(IncrementFileName);
                int result;
                if(Int32.TryParse(lines, out result))
                {
                    Increment = result + 1;
                }
                else
                {
                    Log.LogError("Unable to parse integer in '{0}' (contents of {1})");
                    return false;
                }
            }
            else
            {
                Increment = 1;
            }

            if (SaveChange)
            {
                File.Delete(IncrementFileName);
                File.WriteAllText(IncrementFileName, Increment.ToString());
            }
            return true;
        }
    }
}

在执行FileUpdateTask之前,我使用此代码获取下一个构建编号:

<IncrementTask 
IncrementFileName="$(BuildNumberFile)" 
SaveChange="false">
  <Output TaskParameter="Increment" PropertyName="Build" />
</IncrementTask>

在通知其他人之前,作为我构建的最后一步:

<IncrementTask 
IncrementFileName="$(BuildNumberFile)" 
SaveChange="true"
Condition="'$(Configuration)' == 'Release'" />

如何只在源代码更改时更新版本号,这个问题取决于您的构建过程与源控制的交互方式。通常,检查源文件更改应该启动持续集成构建。这是用来更新相关版本号的。


0

我已经编写了一个自定义任务,您可以参考下面的代码。它将创建一个实用程序,您可以通过它传递assemblyinfo路径、主要、次要和构建号。您可以修改它以获取修订号。由于在我的情况下,这个任务是由开发人员完成的,所以我不得不搜索它并再次替换整个字符串。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;

namespace UpdateVersion
{
    class SetVersion
    {
        static void Main(string[] args)
        {
            String FilePath = args[0];
            String MajVersion=args[1];
            String MinVersion = args[2];
            String BuildNumber = args[3];
            string RevisionNumber = null;

            StreamReader Reader = File.OpenText(FilePath);
            string contents = Reader.ReadToEnd();
            Reader.Close();

            MatchCollection match = Regex.Matches(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", RegexOptions.IgnoreCase);
            if (match[0].Value != null)
            {
                string strRevisionNumber = match[0].Value;

                RevisionNumber = strRevisionNumber.Substring(strRevisionNumber.LastIndexOf(".") + 1, (strRevisionNumber.LastIndexOf("\"")-1) - strRevisionNumber.LastIndexOf("."));

                String replaceWithText = String.Format("[assembly: AssemblyVersion(\"{0}.{1}.{2}.{3}\")]", MajVersion, MinVersion, BuildNumber, RevisionNumber);
                string newText = Regex.Replace(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", replaceWithText);

                StreamWriter writer = new StreamWriter(FilePath, false);
                writer.Write(newText);
                writer.Close();
            }
            else
            {
                Console.WriteLine("No matching values found");
            }
        }
    }
}

0

我不想这么说,但是你可能做错了。如果你在运行时生成汇编版本,而不是尝试修补它们,那么会更容易。

看一下https://sbarnea.com/articles/easy-windows-build-versioning/

为什么我认为你做错了呢? * 构建不应修改版本号 * 如果你两次构建相同的变更集,你应该得到相同的构建号 * 如果你把构建号放在微软称之为构建号(正确的命名应该是补丁级别)的地方,你最终会达到65535的限制。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接