【问题标题】:How can I use MSBuild to update version information only when an assembly has changed?仅当程序集发生更改时,如何使用 MSBuild 更新版本信息?
【发布时间】:2010-09-18 09:43:18
【问题描述】:

我需要将多个 Web 设置项目(使用 VS2005 和 ASP.Net/C#)安装到同一个虚拟文件夹中。这些项目共享一些程序集引用(文件系统都被构造为使用相同的“bin”文件夹),使对这些程序集的更改的部署有问题,因为 MS 安装程序只会在当前安装的版本比微星。

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

另一方面,重要的是不要自发更新版本号并将 all 常用程序集替换为 every 安装,因为这可能(至少暂时) 进行实际更改的模糊案例。

也就是说,我正在寻找的是一种仅在程序集组成部分(代码模块、资源等)已经/已经实际更改的情况下更新程序集版本信息(最好使用 MSBuild)的方法。

我找到了一些至少部分相关的参考资料here (MSDN 上的 AssemblyInfo 任务)和here(看起来与我需要的相似,但已有两年多的历史,并且没有明确的解决方案)。

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

任何帮助将不胜感激。

提前致谢。

【问题讨论】:

    标签: c# asp.net installation


    【解决方案1】:

    我不想这么说,但您似乎做错了。如果您确实动态生成程序集版本而不是尝试修补它们,那么会容易得多。

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

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

    【讨论】:

      【解决方案2】:

      我写了一个客户任务,你可以参考下面的代码。它将创建一个实用程序,您可以将程序集信息路径主要、次要和内部版本号传递给该实用程序。您可以对其进行修改以获取修订号。因为在我的情况下,这个任务是由开发人员完成的,我曾经搜索它并再次替换整个字符串。

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

      【讨论】:

        【解决方案3】:

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

        但我可以推荐一种比使用 AssemblyInfo 任务更好的方法来更新您的 AssemblyInfo.cs 文件。该任务似乎只是从头开始重新创建标准 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'" />
        

        关于如何仅在源代码发生更改时更新版本号的其他问题在很大程度上取决于您的构建过程如何与源代码管理进行交互。通常,签入源文件更改应该启动持续集成构建。那是用来更新相关版本号的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-15
          • 2018-12-04
          • 2016-05-01
          • 2014-12-07
          • 1970-01-01
          相关资源
          最近更新 更多