Автоматична версія в 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.