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


112

Я витратив більшу частину кількох годин, намагаючись знайти спосіб автоматичного збільшення версій у .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
Дякуємо за інформацію. Це просто відкриває додаткові параметри.
— Jason H

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

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

Відповіді:


23

Я шукав інвертор версій для програми Net Core у VS2017 у форматі конфігурації csproj.

Я знайшов проект під назвою dotnet bump, який працював у форматі project.json, але намагався знайти рішення для формату .csproj. Письменник, натхненник dotnet, фактично придумав рішення для формату .csproj, і це називається MSBump.

Є проект на GitHub для нього за адресою:

https://github.com/BalassaMarton/MSBump

де ви можете побачити код і його доступний і в Nuget. Просто шукайте MSBump на Nuget.


1
Я рекомендую використовувати останню версію 2.1.0 MSBump, вона підтримує перемикання конфігурацій краще, а також встановлює версію для поточної збірки, а не наступну (як попередня версія).
— Márton Balassa

Я бачу, зараз він також підтримує MSBuild, тоді як до цього потрібна візуальна студія.
— ravetroll

2
Так, і він також підтримує проекти з багатоцільовим націленням.
— Márton Balassa

4
Подумайте про використання GitVersioning. Це може бути придатним для запуску у вашому середовищі CI. github.com/AArnott/Nerdbank.GitVersioning
— Henrique

1
Версія з збільшенням MSBump для кожної збірки, навіть якщо ви нічого не змінили, це спричиняє багато проблем у довгостроковій перспективі. І іноді версії не синхронізуються, і одна версія відстає від іншої.
— Конрад

68

Додати <Deterministic>False</Deterministic> всередину <PropertyGroup>розділу .csproj

Вирішення способу зробити AssemblyVersion * описано у розділі "Помітне повідомлення про помилку для підстановки у [AssemblyVersion] on .Net Core # 22660"

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

Причини, через які .Net Core Developer вважає детерміновані збірки корисними, описані в 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
— Майкл Freidgeim

62

Якщо ви використовуєте службу / Visual Studio Team Services / TFS або інший процес збирання CI для вбудованої версії, ви можете використовувати Conditionатрибут msbuild , наприклад:

<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

Гарне рішення. Я все ж отримав виняток Build. Мені довелося трохи змінити конфігурацію, щоб виправити це. 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 (необов'язково) при введенні та повертає генеровану версію у вихідному властивості версії. Логіка отримання номерів версій така ж, як і автоматичне оновлення .NET (число збірки - це кількість днів, починаючи з 1/1/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>

Тут важливі речі:

  • Згадано за допомогою використання імпорту завдань GetCurrentBuildVersion з DC.Build.Tasks.dll . Він передбачає, що цей dll-файл знаходиться в батьківському каталозі з вашого .csproj-файлу.
  • Наша передBuildActionsProject1 Завдання, яка має завдання для викликів, повинна мати унікальну назву для кожного проекту, якщо у нас є більше проектів у рішенні, яке викликає завдання GetCurrentBuildVersion.

Перевага цього рішення полягає в тому, що воно працює не тільки з побудов на сервері збірки, але і в ручних побудовах з dotnet build або Visual Studio.


4
Я рекомендую використовувати DateTime.UtcNowзамість DateTime.Nowметоду, GetCurrentBuildVersionString()зокрема, якщо код виконується на автоматизованих складальних машинах. Вони можуть працювати в 2 години ранку або 3 години ночі, коли ваш комп'ютер переходить на / з літнього часу. З DateTime.Nowцим сценарієм ви, можливо, будете йти назад у версії. Справді, це кутовий випадок, і я також визнаю, що я прискіпливий. :-) Крім того, проблема також усувається, якщо ви налаштували однаковий часовий пояс на всіх машинах, що складаються, і не налаштовувати на літній час.
— Манфред

Чи є ще пакет NuGet для цього?
— Джонатан Аллен

@Jonathan Allen Ні, я не маю плану для пакунків з нуджетами через різну назву в кожному проекті. Ви можете завантажити складену збірку завдань для збирання в 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 build /p:AssemblyVersion=1.2.3.4

Я відповідав: "хтось придумав, як контролювати версію в проектах .NET Core (або .NETStandard для цього питання)." Я знайшов це питання, намагаючись вирішити цю проблему в контексті побудови ІС. Я хотів встановити версію збірки на номер збірки CI.


1
У заголовку написано "Автоматична версія у Visual Studio 2017 (.NET Core)". Де саме його побудова вручну відповідає "Visual Studio 2017"?
— JCKödel

4
Я відповідав: "хтось придумав, як контролювати версію в проектах .NET Core (або .NETStandard для цього питання)." Я знайшов це питання, намагаючись вирішити цю проблему в контексті побудови ІС. Я хотів встановити версію збірки на номер збірки CI. Вибачте, якщо ви вважаєте, що це не стосується питання, що знаходиться у вас.
— Кріс Маккензі

Це корисна складова для мене спасибі. Я буду використовувати це як частину рішення CI
— Марк Адамсон,

1
@ChrisMcKenzie: ваш коментар повинен бути включений у вашу відповідь, щоб
— уточнити

** це не працює для мене в проектах netstandard, коли Assemblyinfo.cs не вказано, а версія знаходиться в csproj ...
— tofutim

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
Я боявся, що це буде відповідь. Я побачу, чи зможу я зробити крок попереднього побудови, щоб збільшити його.
— Джейсон H

3
Як зазначається в іншій нитці, новий формат csproj дозволяє вимкнути автоматичну генерацію файлу Assemblyinfo та вказати свій власний. Я дотримувався поради відповіді natemcmaster тут і використовував стандартний файл AssemblyInfo.cs: stackoverflow.com/questions/42138418/…
— Джеймс Ебі,

5
Чому вони видалили автоматичне збільшення? Роками це працювало дуже добре і дуже просто. Я натискаю master, CI будує та збільшує, потім версія читається безпосередньо з вбудованої DLL за допомогою якогось сценарію PS, потім використовую цю версію як аргумент при натисканні на NuGet. Так просто. Зараз зламаний.
— Люк Пуплетт

1
@LukePuplett те саме тут. так засмучує!
— Шиммі Вайцхандлер

@LukePuplett: Дивіться [“Заплутане повідомлення про помилку для підстановки у AssemblyVersion у .Net Core # 22660”] ( github.com/dotnet/roslyn/isissue/22660 ), причини, які вважають Детерміновані побудови корисними, описані в blog.paranoidcoding.com / 2016/04/05 /… і компілятори повинні бути детермінованими: одні й ті ж входи генерують однакові виходи # 372 < github.com/dotnet/roslyn/isissue/372 >
— Michael Freidgeim,

5

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


@JasonH Спасибі, дайте мені знати, якщо у вас є якісь проблеми з цим.
— Tagc

проклятий геній. любити це!
— 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>

EDIT: Якщо ви будуєте за допомогою 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.