Pembuatan Versi Otomatis di Visual Studio 2017 (.NET Core)

112

Saya telah menghabiskan sebagian besar dari beberapa jam mencoba menemukan cara untuk versi penambahan otomatis di .NETCoreApp 1.1 (Visual Studio 2017).

Saya tahu AssemblyInfo.cs sedang dibuat secara dinamis di dalam folder: obj/Debug/netcoreapp1.1/

Itu tidak menerima metode lama: [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.*")]

Jika saya mengatur proyek ke paket, saya dapat mengatur versi di sana tetapi ini tampaknya digunakan untuk membangun file AssemblyInfo.cs.

Pertanyaan saya adalah, apakah ada yang tahu cara mengontrol versi di proyek .NET Core (atau .NETStandard dalam hal ini).

Jason H.
sumber
Saya tidak tahu seberapa jauh Anda melakukannya, tetapi sepertinya saya menanyakan pertanyaan yang hampir sama dengan cara yang berbeda ( stackoverflow.com/a/43280282/685341 ) - Mungkin jawaban yang diterima untuk pertanyaan ini akan membantu Anda; Anda bisa meneruskan /p:bendera ke dotnet msbuilddalam skrip build Anda dan menyetel versi, perusahaan, hak cipta ... semua hal bagus itu.
Jay
2
Terimakasih atas infonya. Itu hanya membuka opsi tambahan.
Jason H
Sebelumnya * didukung untuk AssemblyVersion, bukan untuk AssemblyFileVersion- lihat Dapatkah saya menaikkan versi pembuatan file secara otomatis saat menggunakan Visual Studio?
Michael Freidgeim
4
FWIW wildcard dalam versi rakitan tidak didukung karena untuk proyek baru ini, mode "deterministik" kompiler aktif secara default. Karena kenaikan otomatis akan merusak determinisme (input yang sama> output yang sama), ini tidak diizinkan dalam mode itu. Anda dapat mengatur <Deterministic>False</Deterministic>di csproj untuk menggunakannya. (atau gunakan logika MSbuild lainnya untuk menghitung <VersionPrefix>/ <Version>)
Martin Ullrich

Jawaban:

23

Saya telah mencari incrementer versi untuk aplikasi Net Core di VS2017 menggunakan format konfigurasi csproj.

Saya menemukan proyek bernama dotnet bump yang berfungsi untuk format project.json tetapi kesulitan menemukan solusi untuk format .csproj. Penulis benjolan dotnet sebenarnya datang dengan solusi untuk format .csproj dan itu disebut MSBump.

Ada proyek di GitHub untuk itu di:

https://github.com/BalassaMarton/MSBump

dimana Anda dapat melihat kode dan juga tersedia di Nuget. Cari saja MSBump di Nuget.

ravetroll
sumber
1
Saya merekomendasikan menggunakan rilis 2.1.0 MSBump terbaru, Ini mendukung konfigurasi switching yang lebih baik, dan juga menetapkan versi untuk build saat ini, bukan yang berikutnya (seperti versi sebelumnya).
Márton Balassa
Saya melihatnya sekarang juga mendukung MSBuild padahal sebelumnya diperlukan studio visual.
ravetroll
2
Ya, dan ini juga mendukung proyek multi-penargetan.
Márton Balassa
4
Pertimbangkan untuk menggunakan GitVersioning. Ini mungkin cocok untuk dijalankan di lingkungan CI Anda. github.com/AArnott/Nerdbank.GitVersioning
Henrique
1
MSBump meningkatkan versi pada setiap versi bahkan jika Anda tidak mengubah apa pun, ini menyebabkan banyak masalah dalam jangka panjang. Dan terkadang versi tidak sinkron dan satu versi berada di belakang yang lain.
Konrad
68

Tambahkan <Deterministic>False</Deterministic> di dalam <PropertyGroup>bagian .csproj

Solusi untuk membuat AssemblyVersion * berfungsi dijelaskan di "Pesan kesalahan membingungkan untuk wildcard di [AssemblyVersion] di .Net Core # 22660"

Karakter pengganti hanya diizinkan jika build tidak deterministik, yang merupakan default untuk project .Net Core. Menambahkan  <Deterministic>False</Deterministic> ke csproj memperbaiki masalah tersebut.

Alasan mengapa .Net Core Developers menganggap Deterministic Build bermanfaat seperti yang dijelaskan di http://blog.paranoidcoding.com/2016/04/05/deterministic-builds-in-roslyn.html dan Compiler harus deterministik: input yang sama menghasilkan output yang sama # 372

Namun jika Anda menggunakan TeamCity, TFS atau alat CI / CD lainnya, mungkin lebih baik untuk tetap mengontrol nomor versi dan menambahkannya dan meneruskan ke build sebagai parameter (seperti yang disarankan dalam jawaban lain), misalnya

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

Nomor paket untuk paket NuGet

msbuild /t:pack /p:Version=YourVersionNumber   
Michael Freidgeim
sumber
Terima kasih! Saya tahu ada tuas tersembunyi untuk membuka ruang harta karun! Saya memigrasi proyek lama ke .NET SDK yang baru, dan saya benar-benar ingin melakukannya dengan cepat, tanpa perlu repot menemukan solusi peningkatan versi otomatis. Faktanya, semakin kompatibel dengan cara lama semakin baik untuk kasus saya.
Ivaylo Slavov
Ini adalah jawaban terbaik IMO. Ini memungkinkan perkakas build berfungsi dengan benar. Setidaknya saya dapat menggunakan mekanisme eksternal untuk memasukkan nomor tersebut ke dalam build sekarang.
Michael Yanni
Harap perluas jawaban Anda sedikit lagi: penambahan yang disarankan harus masuk ke bagian <PropertyGroup> dari .csproj. Dan terima kasih atas jawaban yang bagus ini, tentu saja!
GerardV
1
@gerardv, selesai, tetapi Anda dapat meningkatkan pengeditan sendiri stackoverflow.com/help/editing
Michael Freidgeim
62

Jika Anda menggunakan Visual Studio Team Services / TFS atau beberapa proses pembuatan CI lainnya untuk memiliki versi built-in, Anda dapat menggunakan Conditionatribut msbuild , misalnya:

<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>

Ini akan memberi tahu compiler .NET Core untuk menggunakan apa pun yang ada di BUILD_BUILDNUMBERvariabel lingkungan jika ada, atau kembali ke 0.0.1-localjika Anda melakukan build di mesin lokal Anda.

joelsand
sumber
Bagus, saya suka pendekatan ini karena variabel enviornment hanya dapat diatur di server build sementara persyaratan ini menentukan kumpulan yang ditetapkan dalam biner.
jbooker
Sepertinya tidak berfungsi pada TFS 2010, tapi mudah-mudahan kami segera pindah!
Mark Adamson
Bukan solusi yang buruk, meski bisa sedikit bekerja jika solusinya memiliki banyak proyek.
tofutim
Solusi bagus. Saya memang mendapatkan pengecualian Build. Saya harus mengubah konfigurasi sedikit untuk memperbaikinya. stackoverflow.com/a/59858009/106227
Stu Harper
Ini berfungsi baik dengan .NET Core 2.1.2 dan TFS2017U3
Dave Johnson
16

Saya datang dengan solusi yang bekerja hampir sama dengan atribut AssemblyVersion lama dengan bintang (*) - AssemblyVersion ("1.0. ") *

Nilai untuk AssemblyVersion dan AssemblyFileVersion ada di file .csproj proyek MSBuild (bukan di AssemblyInfo.cs ) sebagai properti FileVersion (menghasilkan AssemblyFileVersionAttribute ) dan AssemblyVersion (menghasilkan AssemblyVersionAttribute ). Dalam proses MSBuild kami menggunakan tugas MSBuild kustom kami untuk menghasilkan nomor versi dan kemudian kami mengganti nilai properti FileVersion dan AssemblyVersion ini dengan nilai baru dari tugas.

Jadi pertama-tama kami membuat tugas MSBuild kustom kami 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();
    }
}

Tugas kelas mewarisi dari Microsoft.Build.Utilities.Task kelas dari Microsoft.Build.Utilities.Core paket nuget. Dibutuhkan properti BaseVersion (opsional) pada input dan mengembalikan versi yang dihasilkan dalam properti keluaran Versi. Logika untuk mendapatkan nomor versi sama dengan pembuatan versi otomatis .NET (Nomor build adalah hitungan hari sejak 1/1/2000 dan Revisi setengah detik sejak tengah malam).

Untuk membangun tugas MSBuild ini, kami menggunakan jenis proyek perpustakaan kelas .NET Standard 1.3 dengan kelas ini.

File .csproj bisa terlihat seperti ini:

<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>

Proyek tugas ini juga tersedia di GitHub holajan / DC.Build.Tasks saya

Sekarang kita mengatur MSBuild untuk menggunakan tugas ini dan mengatur properti FileVersion dan AssemblyVersion . Dalam file .csproj terlihat seperti ini:

<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>

Hal-hal penting di sini:

  • UsingTask yang disebutkan mengimpor tugas GetCurrentBuildVersion dari DC.Build.Tasks.dll . Diasumsikan bahwa file dll ini terletak di direktori induk dari file .csproj Anda.
  • Target BeforeBuildActionsProject1 kami yang memanggil tugas harus memiliki nama unik per proyek jika kami memiliki lebih banyak proyek dalam solusi yang memanggil tugas GetCurrentBuildVersion.

Keuntungan dari solusi ini adalah ia berfungsi tidak hanya dari build di server build, tetapi juga dalam build manual dari build dotnet atau Visual Studio.

HolaJan
sumber
4
Saya akan merekomendasikan untuk menggunakan DateTime.UtcNowalih-alih DateTime.Nowdalam metode GetCurrentBuildVersionString()khususnya jika kode dijalankan pada mesin pembuat otomatis. Mereka mungkin berjalan pada jam 2 pagi atau 3 pagi saat komputer Anda beralih ke / dari waktu musim panas. Dengan DateTime.Nowskenario itu Anda mungkin akan mundur dalam hal versi. Memang, ini adalah kasus sudut dan saya juga mengakui bahwa saya pilih-pilih. :-) Selain itu, masalahnya juga akan hilang jika Anda mengonfigurasi zona waktu yang sama di semua mesin build dan tidak menyesuaikan dengan waktu musim panas.
Manfred
Apakah sudah ada paket NuGet untuk ini?
Jonathan Allen
@Jonathan Allen Tidak, saya tidak punya rencana untuk paket nuget, karena nama berbeda di setiap proyek. Anda dapat mengunduh compile build task assemby di github.com/holajan/DC.Build.Tasks/tree/master/dist folder
HolaJan
Kami telah menggunakan aplikasi konsol khusus untuk mengambil versi kami dari server dan menghasilkan file AssemblyInfo.cs sebelum membangun. Pendekatan ini sempurna untuk apa yang kami lakukan. Apakah Anda dapat menggunakan metode ini untuk mendorong versi dalam "Versi" dari fitur paket proyek baru? Ini akan menyenangkan, tapi saya rasa kita dapat kembali menggunakan nuget.exe untuk membuat paket juga karena kita akan membutuhkannya untuk mempublikasikannya juga.
David Ritchie
15

Anda dapat menggunakan fungsi properti MSBuild untuk menyetel akhiran versi berdasarkan tanggal saat ini:

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

Ini akan menampilkan paket dengan nama seperti: PackageName.1.0.0-pre20180807-1711.nupkg .

Rincian lebih lanjut tentang fungsi properti MSBuild: https://docs.microsoft.com/en-us/visualstudio/msbuild/property-functions

The Versionterbentuk dari kombinasi VersionPrefixdan VersionSuffix, atau jika VersionSuffixkosong, VersionPrefixhanya.

<PropertyGroup>
  <VersionPrefix>1.0.0</VersionPrefix>
</PropertyGroup>
Fabricio Godoy
sumber
Ini sangat berguna
Jerry Nixon
12

Saya menerima jawaban di atas karena @Gigi benar (seperti yang sekarang) tetapi saya kesal dan muncul dengan Skrip PowerShell berikut.

Pertama saya memiliki skrip di folder solusi saya (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)

Saya menambahkan ini ke file 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>

Bahkan melalui setnya menjadi PreBuildEvent, faktanya adalah nomor versi tidak diperbarui sampai SETELAH file telah dimuat ke memori sehingga nomor versi tidak akan mencerminkan sampai pembuatan berikutnya. Faktanya, Anda dapat mengubahnya menjadi PostBuildEvent dan itu akan memiliki efek yang sama.

Saya juga membuat dua skrip berikut: (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)
Jason H.
sumber
10

dotnet build /p:AssemblyVersion=1.2.3.4

Saya menanggapi: "apakah ada yang tahu cara mengontrol versi dalam proyek .NET Core (atau .NETStandard dalam hal ini)." Saya menemukan pertanyaan ini mencoba memecahkan masalah ini dalam konteks build CI. Saya ingin mengatur versi perakitan ke nomor build CI.

Chris McKenzie
sumber
1
Judulnya mengatakan "Auto Versioning in Visual Studio 2017 (.NET Core)". Di mana tepatnya membangunnya secara manual sesuai dengan "Visual Studio 2017"?
JCKödel
4
Saya menanggapi: "apakah ada yang tahu cara mengontrol versi dalam proyek .NET Core (atau .NETStandard dalam hal ini)." Saya menemukan pertanyaan ini mencoba memecahkan masalah ini dalam konteks build CI. Saya ingin mengatur versi perakitan ke nomor build CI. Saya minta maaf jika Anda merasa ini tidak relevan dengan pertanyaan yang ada.
Chris McKenzie
Ini komponen yang sangat membantu bagi saya, terima kasih. Saya akan menggunakan ini sebagai bagian dari solusi CI
Mark Adamson
1
@ChrisMcKenzie: komentar Anda harus disertakan dalam jawaban Anda untuk memperjelas maksud Anda
Michael Freidgeim
** ini tidak berfungsi untuk saya pada proyek netstandard ketika assemblyinfo.cs tidak ditentukan dan versinya ada di csproj ...
tofutim
9

Nilai-nilai ini sekarang ditetapkan di .csprojfile:

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

Ini adalah nilai yang sama yang Anda lihat jika Anda masuk ke tab Paket di pengaturan proyek. Meskipun menurut saya Anda tidak dapat menggunakan *untuk meningkatkan versi secara otomatis, yang dapat Anda lakukan adalah memperkenalkan langkah pasca-pemrosesan yang menggantikan versi untuk Anda (misalnya sebagai bagian dari integrasi berkelanjutan Anda).

Gigi
sumber
6
Saya takut ini akan menjadi jawabannya. Saya akan melihat apakah saya dapat melakukan langkah pra-bangun untuk meningkatkannya.
Jason H
3
Seperti yang ditunjukkan di utas lain, format csproj yang baru memungkinkan Anda mematikan pembuatan otomatis file assemblyinfo dan Anda dapat menentukannya sendiri. Saya mengikuti saran dari jawaban natemcmaster di sini dan menggunakan file AssemblyInfo.cs standar: stackoverflow.com/questions/42138418/…
James Eby
5
Mengapa mereka menghapus kenaikan otomatis? Ini bekerja dengan sangat baik dan sangat sederhana untuk saya selama bertahun-tahun. Saya mendorong master, CI build dan increments, lalu versinya dibaca langsung dari DLL yang dibuat menggunakan beberapa skrip PS, lalu gunakan versi itu sebagai argumen saat mendorong ke NuGet. Sangat sederhana. Sekarang rusak.
Luke Puplett
1
@ LukePuplett sama di sini. sangat membuat frustasi!
Shimmy Weitzhandler
@LukePuplett: Lihat [“Pesan kesalahan yang membingungkan untuk wildcard di AssemblyVersion pada .Net Core # 22660”] ( github.com/dotnet/roslyn/issues/22660 ), Alasan mengapa mereka menganggap Deterministic Build bermanfaat dijelaskan di blog.paranoidcoding.com / 2016/04/05 /… dan Penyusun harus deterministik: masukan yang sama menghasilkan keluaran yang sama # 372 < github.com/dotnet/roslyn/issues/372 >
Michael Freidgeim
5

Saya membuat alat CLI sederhana untuk mengatur string versi .csproj .NET Core di sini . Anda dapat menggabungkannya dengan alat seperti GitVersion untuk peningkatan versi otomatis selama pembuatan CI, jika itu yang Anda cari.

Tagc
sumber
@JasonH Terima kasih, beri tahu saya jika Anda mengalami masalah.
Tagc
jenius sekali. suka!
pms1969
4

Untuk mengaktifkan pembuatan versi .Net Core / .Net Proyek apa pun berdasarkan penyiapan GIT Anda, gunakan fungsi tag / deskripsikan GIT.

Saya telah menggunakan file Prebuild.t target.xml yang terletak di folder root untuk proyek dan termasuk dalam file csproj seperti:

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

Gunakan tag "GenerateAssembyInfo" untuk menonaktifkan pembuatan info perakitan otomatis.

Kemudian Prebuild.target.xml akan menghasilkan file CommonAssemblyInfo.cs di mana Anda dapat memasukkan tag versi yang Anda inginkan berdasarkan versi GIT Anda

CATATAN: Saya telah menemukan Prebuilds.t target.xml di tempat lain, jadi belum repot-repot membersihkannya.)

File Prebuild.t target.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: Jika Anda membangun menggunakan MSBUILD

 $(SolutionDir)

Mungkin membuatmu kesulitan, gunakan

 $(ProjectDir)

sebagai gantinya

Tue Skeltved
sumber
Bagus! Apakah VersionSuffix akhirnya disetel atau digunakan? Sepertinya tidak
Mark Adamson
4

Anda dapat melakukan hal di bawah ini, di dalam file csproj. Saya tidak mengerti matematika. Saya menemukan itu di tempat lain di stackoverflow. Tapi ini berfungsi dan akan memberi Anda sesuatu yang mirip dengan 1.0. * Untuk versi.

<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>
Clarke76
sumber
3

Ekstensi Versi Otomatis untuk Visual Studio sekarang mendukung .Net Core dan .Net Standard autoincrementing dalam antarmuka pengguna yang sederhana.

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

Madamission
sumber
1
Saya telah melakukan tes cepat dengan solusi demo (aplikasi windows) dan berfungsi, juga dengan proyek standar .net. Itu adalah tes cepat jadi harus menyelam lebih dalam untuk memeriksa apakah semua yang kita inginkan. Tapi Anda pasti bisa mencoba yang ini.
ArieKanarie
3

Terima kasih kepada @joelsand karena telah mengarahkan saya ke arah yang benar.

Saya harus mengubah jawabannya sedikit karena ketika DevOps Build dijalankan, saya mendapat pengecualian berikut

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

Saya harus menambahkan $ (BUILD_BUILDNUMBER) di akhir bagian major.minor.build. Untuk menghapus duplikat versi sebenarnya, saya juga menggunakan awalan versi:

<PropertyGroup>
    <VersionPrefix>1.0.3</VersionPrefix>
    <Version Condition=" '$(BUILD_BUILDNUMBER)' == '' ">$(VersionPrefix)-local</Version>
    <Version Condition=" '$(BUILD_BUILDNUMBER)' != '' ">$(VersionPrefix)-$(BUILD_BUILDNUMBER)</Version>
</PropertyGroup>
Stu Harper
sumber
Saya memiliki masalah yang persis sama dan jawaban Anda memperbaikinya. Terima kasih.
Rapat Hadir
2

Kita dapat menggunakan parameter khusus untuk dotnet publish -- version-suffix 1.2.3

Untuk versi file:

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

Untuk versi:

<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.
Anatoli Klamer
sumber
1

Saya rasa Jawaban dari @joelsand ini adalah jawaban yang benar untuk mengatur nomor versi untuk inti dotnet yang berjalan di VSTS

Untuk menambahkan lebih banyak informasi untuk jawaban ini,

BUILD_BUILDNUMBERsebenarnya adalah variabel yang telah ditentukan sebelumnya .

Ternyata ada 2 versi variabel standar.

Salah satunya adalah build.xxxx, yang lainnya adalah BUILD_XXXX.

Anda hanya dapat menggunakan Environment Variable Namedi cproj.

maxisam
sumber
Tidak build.xxxxdigunakan di front end untuk mereferensikan dalam pipeline dan BUILD_XXXXmemiliki nilai yang sama tetapi dengan sintaks yang sedikit dimodifikasi diperlukan untuk mereferensikan variabel di PS?
dst3p