Автоматическое управление версиями в Visual Studio 2017 (.NET Core)


113

Я потратил большую часть нескольких часов, пытаясь найти способ автоматического увеличения версий в .NETCoreApp 1.1 (Visual Studio 2017).

Я знаю, что AssemblyInfo.cs динамически создается в папке: obj/Debug/netcoreapp1.1/

Он не принимает старый метод: [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.*")]

Если я установлю пакет для проекта, я могу установить там версии, но, похоже, это будет использоваться для создания файла AssemblyInfo.cs.

Мой вопрос: кто-нибудь понял, как управлять версией в проектах .NET Core (или .NETStandard, если на то пошло).


Я не знаю, как далеко вы продвинулись в этом, но похоже, что я задал почти тот же вопрос другим способом ( stackoverflow.com/a/43280282/685341 ). Возможно, принятый ответ на этот вопрос поможет вам; вы можете просто передать /p:флаг dotnet msbuildв свой скрипт сборки и установить версию, компанию, авторские права ... все это хорошее.
— Джей

2
Спасибо за информацию. Это просто открывает дополнительные возможности.
— Джейсон Х

Ранее * поддерживался для AssemblyVersion, а не для AssemblyFileVersion - см. Могу ли я автоматически увеличивать версию сборки файла при использовании Visual Studio?
— Майкл

4
FWIW подстановочный знак в версии сборки не поддерживается, потому что для этого нового проекта "детерминированный" режим компилятора активен по умолчанию. Поскольку автоинкремент нарушит детерминизм (тот же ввод> тот же вывод), в этом режиме он запрещен. Вы можете настроить его <Deterministic>False</Deterministic>в csproj. (или используйте любую другую логику MSbuild для вычисления <VersionPrefix>/ <Version>)
— Мартин Ульрих

Ответы:


23

Я искал инкремент версии для приложения Net Core в VS2017 с использованием формата конфигурации csproj.

Я нашел проект под названием dotnet bump, который работал с форматом project.json, но изо всех сил пытался найти решение для формата .csproj. Создатель dotnet bump фактически предложил решение для формата .csproj, и оно называется MSBump.

Для этого есть проект на GitHub:

https://github.com/BalassaMarton/MSBump

где вы можете увидеть код, а также его доступность на Nuget. Просто найдите MSBump на Nuget.


1
Я рекомендую использовать последнюю версию MSBump 2.1.0, она лучше поддерживает переключение конфигураций, а также устанавливает версию для текущей сборки, а не для следующей (как предыдущая версия).
— Мартон Баласса,

Я вижу, что теперь он также поддерживает MSBuild, тогда как раньше для этого требовалась визуальная студия.
— ravetroll

2
Да, и он также поддерживает проекты с несколькими целями.
— Márton Balassa

4
Рассмотрите возможность использования GitVersioning. Он может быть подходящим для работы в вашей среде CI. github.com/AArnott/Nerdbank.GitVersioning
— Henrique

1
MSBump увеличивает версию при каждой сборке, даже если вы ничего не меняли, в долгосрочной перспективе это вызывает множество проблем. А иногда версии не синхронизируются, и одна версия отстает от другой.
— Конрад

69

Добавить <Deterministic>False</Deterministic> в <PropertyGroup>раздел .csproj

Обходной путь, заставляющий AssemblyVersion * работать, описан в «Непонятном сообщении об ошибке для подстановочного знака в [AssemblyVersion] в .Net Core # 22660»

Подстановочные знаки разрешены только в том случае, если сборка не является детерминированной, что по умолчанию для проектов .Net Core. Добавление  <Deterministic>False</Deterministic> в csproj устраняет проблему.

Причины, по которым разработчики .Net Core считают детерминированные сборки полезными, описаны в http://blog.paranoidcoding.com/2016/04/05/deterministic-builds-in-roslyn.html, а компиляторы должны быть детерминированными: одинаковые входные данные генерируют одинаковые выходные данные # 372

Однако, если вы используете TeamCity, TFS или другой инструмент CI / CD, вероятно, лучше держать номер версии под контролем и увеличивать их и передавать для сборки в качестве параметра (как было предложено в других ответах), например

msbuild /t:build /p:Version=YourVersionNumber /p:AssemblyVersion=YourVersionNumber

Номер пакета для пакетов NuGet

msbuild /t:pack /p:Version=YourVersionNumber   

Спасибо! Я знал, что есть скрытый рычаг для открытия сокровищницы! Я переношу старый проект на новый .NET SDK, и мне очень хотелось сделать это быстро, без хлопот по поиску решений для автоматического увеличения версии. На самом деле, чем больше совместимо со старыми способами, тем лучше для моего случая.
— Ивайло Славов

Это лучший ответ ИМО. Это позволяет инструментам сборки работать правильно. По крайней мере, теперь я могу использовать внешний механизм для ввода числа в сборку.
— Майкл Янни

Пожалуйста, расширите свой ответ еще немного: предлагаемое дополнение должно быть в разделе <PropertyGroup> файла .csproj. И, конечно, спасибо за отличный ответ!
— GerardV

1
@gerardv, готово, но вы можете улучшить правки самостоятельно stackoverflow.com/help/editing
— Майкл Фрейдгейм,

62

Если вы используете Visual Studio Team Services / TFS или какой-либо другой процесс сборки CI для встроенного управления версиями, вы можете использовать атрибут msbuild Condition, например:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <Version Condition=" '$(BUILD_BUILDNUMBER)' == '' ">0.0.1-local</Version>
    <Version Condition=" '$(BUILD_BUILDNUMBER)' != '' ">$(BUILD_BUILDNUMBER)</Version>
    <TargetFramework>netcoreapp1.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Folder Include="wwwroot\" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
    <PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
    <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="1.1.2" />
  </ItemGroup>

</Project>

Это укажет компилятору .NET Core использовать все, что находится в BUILD_BUILDNUMBERпеременной среды, если она есть, или вернуться к ней, 0.0.1-localесли вы выполняете сборку на своем локальном компьютере.


Хорошо, мне нравится этот подход, потому что переменные окружения можно просто установить на сервере сборки, в то время как эти условные выражения определяют набор сборки в двоичных файлах.
— jbooker

Похоже, не работает с TFS 2010, но, надеюсь, мы скоро перейдем к этому!
— Марк Адамсон

Неплохое решение, хотя может потребоваться немного работы, если в решении много проектов.
— tofutim 02

Хорошее решение. Однако я получил исключение сборки. Пришлось немного изменить конфиг, чтобы это исправить. stackoverflow.com/a/59858009/106227
— Стю Харпер,

Это отлично работает с .NET Core 2.1.2 и TFS2017U3
— Дэйв Джонсон,

16

Я придумал решение, которое работало почти так же, как старый атрибут AssemblyVersion со звездочкой (*) - AssemblyVersion ("1.0. ") *

Значения для AssemblyVersion и AssemblyFileVersion находятся в файле .csproj проекта MSBuild (не в AssemblyInfo.cs ) как свойство FileVersion (генерирует AssemblyFileVersionAttribute ) и AssemblyVersion (генерирует AssemblyVersionAttribute ). В процессе MSBuild мы используем нашу настраиваемую задачу MSBuild для генерации номеров версий, а затем переопределяем значения этих свойств FileVersion и AssemblyVersion новыми значениями из задачи.

Итак, сначала мы создаем нашу настраиваемую задачу MSBuild GetCurrentBuildVersion :

public class GetCurrentBuildVersion : Task
{
    [Output]
    public string Version { get; set; }
 
    public string BaseVersion { get; set; }
 
    public override bool Execute()
    {
        var originalVersion = System.Version.Parse(this.BaseVersion ?? "1.0.0");
 
        this.Version = GetCurrentBuildVersionString(originalVersion);
 
        return true;
    }
 
    private static string GetCurrentBuildVersionString(Version baseVersion)
    {
        DateTime d = DateTime.Now;
        return new Version(baseVersion.Major, baseVersion.Minor,
            (DateTime.Today - new DateTime(2000, 1, 1)).Days,
            ((int)new TimeSpan(d.Hour, d.Minute, d.Second).TotalSeconds) / 2).ToString();
    }
}

Задача класса унаследованы от Microsoft.Build.Utilities.Task класса из Microsoft.Build.Utilities.Core пакета NuGet. Он принимает свойство BaseVersion (необязательно) на входе и возвращает сгенерированную версию в свойстве вывода Version. Логика получения номеров версий такая же, как и для автоматического управления версиями .NET (номер сборки - это количество дней с 01.01.2000, а версия - полсекунды с полуночи).

Для создания этой задачи MSBuild мы используем тип проекта библиотеки классов .NET Standard 1.3 с этим классом.

Файл .csproj может выглядеть так:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard1.3</TargetFramework>
    <AssemblyName>DC.Build.Tasks</AssemblyName>
    <RootNamespace>DC.Build.Tasks</RootNamespace>
    <PackageId>DC.Build.Tasks</PackageId>
    <AssemblyTitle>DC.Build.Tasks</AssemblyTitle>
  </PropertyGroup>
 
  <ItemGroup>
    <PackageReference Include="Microsoft.Build.Framework" Version="15.1.1012" />
    <PackageReference Include="Microsoft.Build.Utilities.Core" Version="15.1.1012" />
  </ItemGroup>
</Project>

Этот проект задачи также доступен в моем GitHub holajan / DC.Build.Tasks

Теперь мы настраиваем MSBuild для использования этой задачи и устанавливаем свойства FileVersion и AssemblyVersion . В файле .csproj это выглядит так:

<Project Sdk="Microsoft.NET.Sdk">
  <UsingTask TaskName="GetCurrentBuildVersion" AssemblyFile="$(MSBuildThisFileFullPath)\..\..\DC.Build.Tasks.dll" />
 
  <PropertyGroup>
    ...
    <AssemblyVersion>1.0.0.0</AssemblyVersion>
    <FileVersion>1.0.0.0</FileVersion>
  </PropertyGroup>
 
  ...
 
  <Target Name="BeforeBuildActionsProject1" BeforeTargets="BeforeBuild">
    <GetCurrentBuildVersion BaseVersion="$(FileVersion)">
      <Output TaskParameter="Version" PropertyName="FileVersion" />
    </GetCurrentBuildVersion>
    <PropertyGroup>
      <AssemblyVersion>$(FileVersion)</AssemblyVersion>
    </PropertyGroup>
  </Target>
 
</Project>

Важные вещи здесь:

  • Упомянутый UsingTask импортирует задачу GetCurrentBuildVersion из DC.Build.Tasks.dll . Предполагается, что этот файл DLL находится в родительском каталоге вашего файла .csproj.
  • Наша цель BeforeBuildActionsProject1, которая вызывает задачу, должна иметь уникальное имя для каждого проекта на тот случай, если у нас есть больше проектов в решении, которое вызывает задачу GetCurrentBuildVersion.

Преимущество этого решения заключается в том, что оно работает не только из сборок на сервере сборки, но и в ручных сборках из сборки dotnet или Visual Studio.


4
Я бы рекомендовал использовать DateTime.UtcNowвместо DateTime.Nowметода GetCurrentBuildVersionString()in, в частности, если код выполняется на машинах автоматической сборки. Они могут работать в 2 или 3 часа ночи, когда ваш компьютер переключается на летнее время и обратно. В DateTime.Nowэтом сценарии вы можете вернуться назад с точки зрения версии. По общему признанию, это угловой случай, и я также признаю, что я придирчив. :-) Кроме того, проблема исчезнет, ​​если вы настроите один и тот же часовой пояс на всех машинах сборки и не будете переходить на летнее время.
— Манфред

Есть ли для этого пакет NuGet?
— Джонатан Аллен

@Jonathan Allen: Нет, у меня нет планов для пакета nuget из-за разных имен в каждом проекте. Вы можете скачать скомпилированную сборку задач сборки в папке github.com/holajan/DC.Build.Tasks/tree/master/dist
— HolaJan

Мы использовали настраиваемое консольное приложение, чтобы получить нашу версию с сервера и создать файл AssemblyInfo.cs перед сборкой. Такой подход идеально подходит для того, что мы делаем. Удалось ли вам использовать этот метод, чтобы поместить версию в «Версия» функции пакета новых проектов? Было бы неплохо, но я думаю, мы можем вернуться к использованию nuget.exe для упаковки, поскольку он нам также понадобится для публикации.
— Дэвид Ричи

15

Вы можете использовать функцию свойства MSBuild, чтобы установить суффикс версии на основе текущей даты:

<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
  <VersionSuffix>pre$([System.DateTime]::UtcNow.ToString(yyyyMMdd-HHmm))</VersionSuffix>
</PropertyGroup>

Будет выведен пакет с таким именем: PackageName.1.0.0-pre20180807-1711.nupkg .

Дополнительные сведения о функциях свойств MSBuild: https://docs.microsoft.com/en-us/visualstudio/msbuild/property-functions

VersionФормируется из комбинации VersionPrefixи VersionSuffix, или если VersionSuffixпусто, VersionPrefixтолько.

<PropertyGroup>
  <VersionPrefix>1.0.0</VersionPrefix>
</PropertyGroup>

Это действительно удобно
— Джерри Никсон

12

Я принял приведенный выше ответ, потому что @Gigi верен (на данный момент), но я был раздражен и придумал следующие сценарии PowerShell.

Сначала у меня есть сценарий в папке с моим решением (UpdateBuildVersion.ps1):

#Get Path to csproj
$path = "$PSScriptRoot\src\ProjectFolder\ProjectName.csproj"

#Read csproj (XML)
$xml = [xml](Get-Content $path)

#Retrieve Version Nodes
$assemblyVersion = $xml.Project.PropertyGroup.AssemblyVersion
$fileVersion = $xml.Project.PropertyGroup.FileVersion

#Split the Version Numbers
$avMajor, $avMinor, $avBuild  = $assemblyVersion.Split(".")
$fvMajor, $fvMinor, $fvBuild = $fileVersion.Split(".")

#Increment Revision
$avBuild = [Convert]::ToInt32($avBuild,10)+1
$fvBuild = [Convert]::ToInt32($fvBuild,10)+1

#Put new version back into csproj (XML)
$xml.Project.PropertyGroup.AssemblyVersion = "$avMajor.$avMinor.$avBuild"
$xml.Project.PropertyGroup.FileVersion = "$fvMajor.$fvMinor.$fvBuild"

#Save csproj (XML)
$xml.Save($path)

Я добавил это в файл csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <AssemblyVersion>0.0.1</AssemblyVersion>
    <FileVersion>0.0.1</FileVersion>
    <PreBuildEvent>powershell.exe –NonInteractive –ExecutionPolicy Unrestricted -command "& {$(SolutionDir)UpdateBuildVersion.ps1}"</PreBuildEvent>
  </PropertyGroup>
</Project>

Даже если для него установлено значение PreBuildEvent, на самом деле номера версий не обновляются до ПОСЛЕ загрузки файла в память, поэтому номер версии не будет отображаться до следующей сборки. Фактически, вы можете изменить его на PostBuildEvent, и это даст тот же эффект.

Я также создал следующие два скрипта: (UpdateMinorVersion.ps1)

#Get Path to csproj
$path = "$PSScriptRoot\src\ProjectFolder\ProjectName.csproj"

#Read csproj (XML)
$xml = [xml](Get-Content $path)

#Retrieve Version Nodes
$assemblyVersion = $xml.Project.PropertyGroup.AssemblyVersion
$fileVersion = $xml.Project.PropertyGroup.FileVersion

#Split the Version Numbers
$avMajor, $avMinor, $avBuild  = $assemblyVersion.Split(".")
$fvMajor, $fvMinor, $fvBuild = $fileVersion.Split(".")

#Increment Minor Version - Will reset all sub nodes
$avMinor = [Convert]::ToInt32($avMinor,10)+1
$fvMinor = [Convert]::ToInt32($fvMinor,10)+1
$avBuild = 0
$fvBuild = 0

#Put new version back into csproj (XML)
$xml.Project.PropertyGroup.AssemblyVersion = "$avMajor.$avMinor.$avBuild"
$xml.Project.PropertyGroup.FileVersion = "$fvMajor.$fvMinor.$fvBuild"

#Save csproj (XML)
$xml.Save($path)

(UpdateMajorVersion.ps1)

#Get Path to csproj
$path = "$PSScriptRoot\src\ProjectFolder\ProjectName.csproj"

#Read csproj (XML)
$xml = [xml](Get-Content $path)

#Retrieve Version Nodes
$assemblyVersion = $xml.Project.PropertyGroup.AssemblyVersion
$fileVersion = $xml.Project.PropertyGroup.FileVersion

#Split the Version Numbers
$avMajor, $avMinor, $avBuild  = $assemblyVersion.Split(".")
$fvMajor, $fvMinor, $fvBuild = $fileVersion.Split(".")

#Increment Major Version - Will reset all sub nodes
$avMajor = [Convert]::ToInt32($avMajor,10)+1
$fvMajor = [Convert]::ToInt32($fvMajor,10)+1
$avMinor = 0
$fvMinor = 0
$avBuild = 0
$fvBuild = 0

#Put new version back into csproj (XML)
$xml.Project.PropertyGroup.AssemblyVersion = "$avMajor.$avMinor.$avBuild"
$xml.Project.PropertyGroup.FileVersion = "$fvMajor.$fvMinor.$fvBuild"

#Save csproj (XML)
$xml.Save($path)

10

сборка dotnet /p:AssemblyVersion=1.2.3.4

Я отвечал: «Кто-нибудь придумал, как управлять версией в проектах .NET Core (или .NETStandard в этом отношении)». Я обнаружил, что этот вопрос пытается решить эту проблему в контексте сборки CI. Я хотел установить версию сборки на номер сборки CI.


1
В названии написано «Автоматическое управление версиями в Visual Studio 2017 (.NET Core)». Где именно сборка вручную соответствует «Visual Studio 2017»?
— JCKödel

4
Я отвечал: «Кто-нибудь придумал, как управлять версией в проектах .NET Core (или .NETStandard в этом отношении)». Я обнаружил, что этот вопрос пытается решить эту проблему в контексте сборки CI. Я хотел установить версию сборки на номер сборки CI. Извините, если вы считаете, что это не имеет отношения к рассматриваемому вопросу.
— Крис Маккензи

Спасибо, это полезный компонент. Я буду использовать это как часть решения CI
— Марк Адамсон,

1
@ChrisMcKenzie: ваш комментарий должен быть включен в ваш ответ, чтобы прояснить ваши намерения
— Майкл

** это не работает для меня в проектах netstandard, когда assemblyinfo.cs не указан, а версия находится в csproj ...
— tofutim 02

9

Эти значения теперь установлены в .csprojфайле:

<PropertyGroup>
    <TargetFramework>netcoreapp1.1</TargetFramework>
    <AssemblyVersion>1.0.6.0</AssemblyVersion>
    <FileVersion>1.0.6.0</FileVersion>
    <Version>1.0.1</Version>
</PropertyGroup>

Это те же значения, которые вы увидите, если перейдете на вкладку « Пакет » в настройках проекта. Хотя я не думаю, что вы можете использовать *автоинкремент версии, вы можете ввести этап постобработки, который заменяет версии для вас (например, как часть вашей непрерывной интеграции).


6
Я боялся, что это будет ответ. Я посмотрю, смогу ли я сделать шаг перед сборкой, чтобы увеличить его.
— Jason H

3
Как указано в другом потоке, новый формат csproj позволяет вам отключить автоматическое создание файла assemblyinfo и указать свой собственный. Я последовал совету natemcmaster answer здесь и использовал стандартный файл AssemblyInfo.cs: stackoverflow.com/questions/42138418/…
— Джеймс Эби

5
Почему убрали автоинкремент? У меня это работало очень хорошо и очень просто в течение многих лет. Я нажимаю master, CI сборки и приращения, затем версия считывается непосредственно из встроенной DLL с использованием некоторого сценария PS, а затем использую эту версию в качестве аргумента при отправке в NuGet. Так просто. Сейчас сломано.
— Люк Пуплетт

1
@LukePuplett здесь тоже самое. так обидно!
— Шимми Вайцхандлер

@LukePuplett: См. [«Непонятное сообщение об ошибке для подстановочного знака в AssemblyVersion на .Net Core # 22660»] ( github.com/dotnet/roslyn/issues/22660 ), Причины, по которым они считают Детерминированные сборки полезными, описаны на сайте blog.paranoidcoding.com / 2016/04/05 /… и компиляторы должны быть детерминированными: одни и те же входные данные генерируют одинаковые выходные данные # 372 < github.com/dotnet/roslyn/issues/372 >
— Майкл

5

Я сделал простой инструмент CLI для установки .csproj версии строк .NET Ключевой здесь . Вы можете комбинировать его с такими инструментами, как GitVersion, для автоматического повышения версии во время сборки CI, если вам это нужно.


@JasonH Спасибо, дайте мне знать, если у вас возникнут проблемы.
— Tagc 03

проклятый гений. любить это!
— pms1969

4

Чтобы включить управление версиями вашего .Net Core / .Net Независимо от проекта, основанного на вашей настройке GIT, используйте теги / описать функциональность GIT.

Я использовал файл Prebuild.targets.xml, который находится в корневой папке проекта и включен в файл csproj, например:

<Project Sdk="Microsoft.NET.Sdk">
  <Import Project="PreBuild.targets.xml" />
  ...
  <PropertyGroup>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>

Используйте тег GenerateAssembyInfo, чтобы отключить автоматическое создание информации о сборке.

Затем Prebuild.targets.xml сгенерирует файл CommonAssemblyInfo.cs, в который вы можете включить теги версии, которые хотите, на основе вашей версии GIT.

ПРИМЕЧАНИЕ: я нашел Prebuilds.targets.xml где-то еще, поэтому не стал его очищать.)

Файл Prebuild.targets.xml:

    <?xml version="1.0" encoding="utf-8" ?>
    <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

      <UsingTask
        TaskName="GetVersion"
        TaskFactory="CodeTaskFactory"
        AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
        <ParameterGroup>
          <VersionString ParameterType="System.String" Required="true" />
          <Version ParameterType="System.String" Output="true" />
          <Commit ParameterType="System.String" Output="true" />
          <VersionSuffix ParameterType="System.String" Output="true" />
        </ParameterGroup>
        <Task>
          <!--<Reference Include="" />-->
          <Using Namespace="System"/>
          <Using Namespace="System.IO"/>
          <Using Namespace="System.Text.RegularExpressions" />
          <Code Type="Fragment" Language="cs">
            <![CDATA[
              var match = Regex.Match(VersionString, @"^(?<major>\d+)\.(?<minor>\d+)(\.?(?<patch>\d+))?-(?<revision>\d+)-(?<commit>[a-z0-9-]+)$");
              int major, minor, patch, revision;
              Int32.TryParse(match.Groups["major"].Value, out major);
              Int32.TryParse(match.Groups["minor"].Value, out minor);
              Int32.TryParse(match.Groups["patch"].Value, out patch);
              Int32.TryParse(match.Groups["revision"].Value, out revision);
              _Version = new Version(major, minor, patch, revision).ToString();
              _Commit = match.Groups["commit"].Value;
            ]]>
          </Code>
        </Task>
      </UsingTask>

      <UsingTask
        TaskName="GitExistsInPath"
        TaskFactory="CodeTaskFactory"
        AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
        <ParameterGroup>
          <Exists ParameterType="System.Boolean" Output="true" />
        </ParameterGroup>
        <Task>
          <!--<Reference Include="" />-->
          <Using Namespace="System"/>
          <Using Namespace="System.IO"/>
          <Using Namespace="System.Text.RegularExpressions" />
          <Code Type="Fragment" Language="cs">
            <![CDATA[
            var values = Environment.GetEnvironmentVariable("PATH");
            foreach (var path in values.Split(';')) {
                var exeFullPath = Path.Combine(path, "git.exe");
                if (File.Exists(exeFullPath)) {
                    Exists = true;
                    return true;
                }
                var cmdFullPath = Path.Combine(path, "git.cmd");
                if (File.Exists(cmdFullPath)) {
                    Exists = true;
                    return true;
            }
            }
            Exists = false;
            ]]>
          </Code>
        </Task>
      </UsingTask>

      <Target Name="CreateCommonVersionInfo" BeforeTargets="CoreCompile">
        <Message Importance="high" Text="CreateCommonVersionInfo" />

        <GitExistsInPath>
          <Output TaskParameter="Exists" PropertyName="GitExists"/>
        </GitExistsInPath>
        <Message Importance="High" Text="git not found!" Condition="!$(GitExists)"/>

        <Exec Command="git describe --tags --long --dirty > $(ProjectDir)version.txt" Outputs="$(ProjectDir)version.txt" WorkingDirectory="$(SolutionDir)" IgnoreExitCode="true" Condition="$(GitExists)">
          <Output TaskParameter="ExitCode" PropertyName="ExitCode" />
        </Exec>
        <Message Importance="high" Text="Calling git failed with exit code $(ExitCode)" Condition="$(GitExists) And '$(ExitCode)'!='0'" />

        <ReadLinesFromFile File="$(ProjectDir)version.txt" Condition="$(GitExists) And '$(ExitCode)'=='0'">
          <Output TaskParameter="Lines" ItemName="OutputLines"/>
        </ReadLinesFromFile>
        <Message Importance="High" Text="Tags: @(OutputLines)" Condition="$(GitExists) And '$(ExitCode)'=='0'"/>

        <Delete Condition="Exists('$(ProjectDir)version.txt')" Files="$(ProjectDir)version.txt"/>

        <GetVersion VersionString="@(OutputLines)" Condition="$(GitExists) And '$(ExitCode)'=='0'">
          <Output TaskParameter="Version" PropertyName="VersionString"/>
          <Output TaskParameter="Commit" PropertyName="Commit"/>
        </GetVersion>

        <PropertyGroup>
          <VersionString Condition="'$(VersionString)'==''">0.0.0.0</VersionString>
        </PropertyGroup>

        <Message Importance="High" Text="Creating CommonVersionInfo.cs with version $(VersionString) $(Commit)" />

        <WriteLinesToFile Overwrite="true" File="$(ProjectDir)CommonAssemblyInfo.cs" Encoding="UTF-8" Lines='using System.Reflection%3B

    // full version: $(VersionString)-$(Commit)

    [assembly: AssemblyVersion("$(VersionString)")]
    [assembly: AssemblyInformationalVersion("$(VersionString)")] 
    [assembly: AssemblyFileVersion("$(VersionString)")]' />

      </Target>
    </Project>

РЕДАКТИРОВАТЬ: если вы строите с помощью MSBUILD,

 $(SolutionDir)

Может вызвать проблемы, используйте

 $(ProjectDir)

вместо


Ницца! Будет ли установлен или использован VersionSuffix? Не похоже
— Марк Адамсон

4

Вы можете сделать следующее в файле csproj. Я не разбирался в математике. Я обнаружил это где-то еще в stackoverflow. Но это работает и даст вам нечто похожее на версию 1.0. *.

<PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <FileVersion>1.0.$([System.DateTime]::UtcNow.Date.Subtract($([System.DateTime]::Parse("2000-01-01"))).TotalDays).$([System.Math]::Floor($([MSBuild]::Divide($([System.DateTime]::UtcNow.TimeOfDay.TotalSeconds), 1.32))))</FileVersion>
    <Version>1.0.$([System.DateTime]::UtcNow.Date.Subtract($([System.DateTime]::Parse("2000-01-01"))).TotalDays)</Version>
</PropertyGroup>

3

Расширение Automatic Versions для Visual Studio теперь поддерживает автоинкремент .Net Core и .Net Standard в простом пользовательском интерфейсе.

https://marketplace.visualstudio.com/items?itemName=PrecisionInfinity.AutomaticVersions


1
Я провел быстрый тест с демонстрационным решением (приложение для Windows), и он работает, также со стандартным проектом .net. Это был быстрый тест, поэтому придется погрузиться глубже, чтобы проверить, все ли получается, что мы хотим. Но вы обязательно можете попробовать это.
— ArieKanarie

3

Спасибо @joelsand за то, что указали мне правильное направление.

Мне пришлось немного изменить его ответ, так как при запуске DevOps Build у меня возникло следующее исключение

The specified version string does not conform to the recommended format - major.minor.build.revision

Мне пришлось добавить $ (BUILD_BUILDNUMBER) в конец раздела major.minor.build. Чтобы исключить дубликат фактической версии, я также использую префикс версии:

<PropertyGroup>
    <VersionPrefix>1.0.3</VersionPrefix>
    <Version Condition=" '$(BUILD_BUILDNUMBER)' == '' ">$(VersionPrefix)-local</Version>
    <Version Condition=" '$(BUILD_BUILDNUMBER)' != '' ">$(VersionPrefix)-$(BUILD_BUILDNUMBER)</Version>
</PropertyGroup>

У меня была такая же проблема, и ваш ответ исправил ее. Спасибо.
— Посетитель встречи

2

Мы можем использовать специальный параметр для dotnet publish -- version-suffix 1.2.3

Для файловой версии:

<AssemblyVersion Condition=" '$(VersionSuffix)' == '' ">0.0.1.0</AssemblyVersion>
<AssemblyVersion Condition=" '$(VersionSuffix)' != '' ">$(VersionSuffix)</AssemblyVersion>

Для версии:

<Version Condition=" '$(VersionSuffix)' == '' ">0.0.1</Version>
<Version Condition=" '$(VersionSuffix)' != '' ">$(VersionSuffix)</Version>

https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish?tabs=netcore21

--version-suffix <VERSION_SUFFIX>     Defines the value for the $(VersionSuffix) property in the project.

1

Я думаю, что этот ответ от @joelsand - правильный ответ для установки номера версии для ядра dotnet, работающего на VSTS

Чтобы добавить дополнительную информацию к этому ответу,

BUILD_BUILDNUMBERна самом деле предопределенная переменная .

Оказывается, есть 2 версии предопределенной переменной.

Один - build.xxxx, другой - BUILD_XXXX.

Вы можете использовать только Environment Variable Nameв cproj.


Не build.xxxxиспользуется во внешнем интерфейсе для ссылки в конвейере и BUILD_XXXXимеет то же значение, но с немного измененным синтаксисом, необходимым для ссылки на переменную в PS?
— dst3p

1

В качестве альтернативы приведенному выше вы можете попробовать фиксированный старший номер с суффиксом на основе текущей даты:

  <PropertyGroup>
    <VersionPrefix>1</VersionPrefix>
    <VersionSuffix>$([System.DateTime]::UtcNow.ToString(yyMM)).$([System.DateTime]::UtcNow.ToString(ddHH)).$([System.DateTime]::UtcNow.ToString(mmss))</VersionSuffix>
    <Version Condition=" '$(VersionSuffix)' == '' ">$(VersionPrefix).0.0.1</Version>
    <Version Condition=" '$(VersionSuffix)' != '' ">$(VersionPrefix).$(VersionSuffix)</Version>
  </PropertyGroup>

У вас есть хорошее решение. Однако не всем нравится использовать DateTime в своих версиях.
— Джейсон Х
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.