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

时间:2008-10-21 19:54:00

标签: c# asp.net installer

我需要在同一个虚拟文件夹中安装多个Web安装项目(使用VS2005和ASP.Net/C#)。这些项目共享一些程序集引用(文件系统都被构造为使用相同的“bin”文件夹),因此部署对这些程序集的更改会出现问题,因为如果当前安装的版本比以前安装的版本旧,则MS安装程序将仅覆盖程序集。 MSI。

我并不是说悲观的安装方案是错误的 - 只是它在我给予的环境中产生了问题。由于有相当数量的通用程序集和大量开发人员可能会更改通用程序集但忘记更新其版本号,因此尝试手动管理版本控制最终会导致安装时出现大量混淆。

在这个问题的另一面,重要的是不要自发更新版本号并用每次安装替换所有通用程序集,因为这可能(暂时至少) )实际变化的模糊案例。

那就是说,我正在寻找的是一种更新程序集版本信息(最好是使用MSBuild)的方法,只有在程序集成分(代码模块,资源等)实际已经发生变化的情况下。

我发现了一些至少部分相关的引用here (MSDN上的AssemblyInfo任务)和here(看起来类似于我需要的内容,但已超过两年且没有明确的解决方案)。

我的团队也使用TFS版本控制,因此自动化解决方案应该包括在构建期间可以检出/出现AssebmlyInfo的方法。

非常感谢任何帮助。

提前致谢。

3 个答案:

答案 0 :(得分:10)

我无法回答您的所有问题,因为我没有使用TFS的经验。

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

出于这个原因,我建议您从MSBuild社区任务项目中查看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'" />

仅在源代码发生变化时如何更新版本号的另一个问题在很大程度上取决于构建过程与源代码控制的交互方式。通常,检入源文件更改应启动持续集成构建。这是用于更新相关版本号的那个。

答案 1 :(得分:0)

我写了一个客户任务,你可以参考下面的代码。它将创建一个实用程序,您可以将assemblyinfo路径传递给Major,minor和build number。你可以修改它以获得修订号。因为在我的情况下,这个任务是由开发人员完成的,我用来搜索它并再次替换整个字符串。

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");
            }
        }
    }
}

答案 2 :(得分:0)

我不想这么说,但似乎你可能做错了。如果你动态生成汇编版本而不是试图修补它们会容易得多。

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

为什么我认为你做错了? *构建不应修改版本号 *如果您构建两次相同的变更集,则应获得相同的构建号 *如果您将内置编号放入微软调用内部编号(正确命名将为PATCH级别),您最终将达到65535限制。