Как я могу использовать MSBuild для обновления информации о версии только при изменении сборки?

У меня есть требование установить несколько проектов веб-установки (с использованием VS2005 и ASP.Net/C#) в одну виртуальную папку. Проекты имеют общие ссылки на сборки (все файловые системы структурированы для использования одной и той же папки bin), что делает развертывание изменений в этих сборках проблематичным, поскольку установщик MS перезапишет сборки только в том случае, если текущая установленная версия старше, чем версия в MSI.

Я не утверждаю, что пессимистическая схема установки неверна - только то, что она создает проблемы в среде, с которой мне было поручено работать. Поскольку существует значительное количество общих сборок и значительное количество разработчиков, которые могут изменить общую сборку, но забывают обновить ее номер версии, попытка управления версиями вручную в конечном итоге приведет к огромной путанице во время установки.

С другой стороны, важно не обновлять номера версий спонтанно и не заменять общие сборки все установкой каждый, поскольку это может (по крайней мере временно) скрыть случаи, когда были внесены фактические изменения.

Тем не менее, то, что я ищу, - это средство для обновления информации о версии сборки (желательно с использованием MSBuild) только в тех случаях, когда компоненты сборки (модули кода, ресурсы и т. д.) Действительно изменились.

Я нашел несколько ссылок, которые хотя бы частично относятся к здесь (задача AssemblyInfo в MSDN) и здесь (похоже на то, что мне нужно, но старше двух лет и без четкого решения).

Моя команда также использует контроль версий TFS, поэтому автоматизированное решение, вероятно, должно включать средства, с помощью которых AssebmlyInfo можно будет извлекать / загружать во время сборки.

Любая помощь приветствуется.

Заранее спасибо.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
0
9 244
3

Ответы 3

Я не могу ответить на все ваши вопросы, так как у меня нет опыта работы с TFS.

Но я могу порекомендовать лучший подход для обновления ваших файлов AssemblyInfo.cs, чем использование задачи AssemblyInfo. Эта задача, по-видимому, просто воссоздает стандартный файл AssemblyInfo с нуля и теряет любые настраиваемые части, которые вы могли добавить.

По этой причине я предлагаю вам изучить задачу FileUpdate из проекта MSBuild Community Tasks. Он может искать конкретное содержимое в файле и заменять его, например:

<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'" />

Другой вопрос о том, как обновить номер версии только при изменении исходного кода, сильно зависит от того, как процесс сборки взаимодействует с системой управления версиями. Обычно проверка изменений исходного файла должна инициировать сборку с непрерывной интеграцией. Это тот, который нужно использовать для обновления соответствующего номера версии.

Я написал одну индивидуальную задачу, вы можете сослаться на приведенный ниже код. Он создаст утилиту, в которую вы можете передать информацию о сборке, путь Major, minor и номер сборки. вы можете изменить его, чтобы получить номер редакции. Поскольку в моем случае эту задачу выполнил разработчик, я искал ее и снова заменял целую строку.

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

Ненавижу это говорить, но похоже, что вы делаете это неправильно. Гораздо проще, если вы создаете версии сборки на лету, а не пытаетесь их исправлять.

Взгляните на https://sbarnea.com/articles/easy-windows-build-versioning/

Почему я думаю, что вы делаете это неправильно? * Сборка не должна изменять номер версии * если вы создадите один и тот же набор изменений дважды, вы должны получить одинаковые номера сборки * если вы поместите номер сборки внутри того, что Microsoft называет номером сборки (правильное имя будет на уровне PATCH), вы в конечном итоге достигнете ограничения 65535.

Другие вопросы по теме