Versioning automatique dans Visual Studio 2017 (.net Core)

j'ai passé la meilleure partie de quelques heures à essayer de trouver un moyen d'auto-incrémentation des versions dans une .NETCoreApp 1.1 (Visual Studio 2017).

I know the AssemblyInfo.cs est créé dynamiquement dans le dossier: obj/Debug/netcoreapp1.1/

il n'accepte pas l'ancienne méthode de: [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.*")]

si je mets le projet à package, je peux y mettre des versions, mais cela semble être utilisé pour construire AssemblyInfo.cs fichier.

ma question Est, quelqu'un a-t-il trouvé comment contrôler la version dans .NET Core (or .NETStandard d'ailleurs.

56
demandé sur Jason H 2017-03-25 20:48:16

13 réponses

j'ai recherché un incrément de version pour une application Net Core dans VS2017 en utilisant le format de configuration csproj.

j'ai trouvé un projet appelé dotnet bump qui a fonctionné pour le projet.JSON format mais a eu du mal à trouver une solution pour le .format csproj. L'écrivain the dotnet bump a trouvé la solution pour le.csproj format et il est appelé MSBump.

il y a un projet sur GitHub pour it à:

https://github.com/BalassaMarton/MSBump

où vous pouvez voir le code et son disponible sur Nuget aussi. Il suffit de chercher pour MSBump sur Nuget.

12
répondu ravetroll 2017-08-08 13:00:31

si vous utilisez Visual Studio Team Services / TFS ou un autre processus de construction de CI pour avoir une version intégrée, vous pouvez utiliser l'attribut Condition de msbuild, par exemple:

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

cela indiquera au compilateur.net D'utiliser tout ce qui est dans la variable d'environnement BUILD_BUILDNUMBER si elle est présente, ou de repli vers 0.0.1-local si vous faites un build sur votre machine locale.

31
répondu joelsand 2017-08-17 15:06:30

ajouter <Deterministic>False</Deterministic> dans une section de <PropertyGroup> .csproj

la solution de contournement pour faire fonctionner AssemblyVersion * est décrite dans "message D'erreur confus pour Joker dans [AssemblyVersion] on .Net Core #22660"

les caractères génériques ne sont autorisés que si la construction n'est pas déterministe, ce qui est la valeur par défaut pour les projets de base. Net. Ajout de <Deterministic>False</Deterministic> aux corrections csproj le question.

les raisons pour lesquelles les développeurs de .net Core considèrent les constructions déterministes bénéfiques décrites dans http://blog.paranoidcoding.com/2016/04/05/deterministic-builds-in-roslyn.html et les compilateurs devraient être déterministes: les mêmes entrées génèrent les mêmes sorties #372

cependant si vous utilisez TeamCity, TFS ou un autre outil CI/CD, il est probablement préférable de conserver le numéro de version contrôlé et incrémenté par eux et passer à construire comme un paramètre ( comme il a été suggéré dans d'autres réponses), par exemple

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

numéro du colis pour les colis NuGet "1519110920

msbuild /t:pack /p:Version=YourVersionNumber   
26
répondu Michael Freidgeim 2018-09-09 21:48:25

j'ai trouvé une solution qui fonctionnait presque comme l'ancienne AssemblyVersion attribut avec star ( * ) - AssemblyVersion ("1.0. ") *

Valeurs AssemblyVersion et AssemblyFileVersion est en projet MSBuild .csproj fichier (et non pas dans AssemblyInfo.cs ) comme propriété FileVersion (génère AssemblyFileVersionAttribute ) et AssemblyVersion (génère AssemblyVersionAttribute ). Dans le processus MSBuild, nous utilisons notre tâche MSBuild personnalisée pour générer des numéros de version, puis nous outrepassons les valeurs de ces propriétés FileVersion et AssemblyVersion avec de nouvelles valeurs de tâche.

donc d'abord nous créons notre tâche personnalisée 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();
    }
}

la classe de tâche hérite de Microsoft.Construire.Utilitaire.Tâche classe de Microsoft.Construire.Utilitaire.Noyau paquet NuGet. Il prend la propriété BaseVersion (optionnelle)sur la propriété input et returns generated version in Version output. La logique pour obtenir les numéros de version est la même que celle du versioning automatique. net (le nombre de compilation est le nombre de jours depuis 1/1/2000 et la révision est d'une demi-seconde depuis minuit.)

pour construire cette tâche MSBuild, nous utilisons le type de projet .net standard 1.3 Class library avec cette classe.

.le fichier csproj peut ressembler à ceci:

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

ce projet de tâche est également disponible dans mon GitHub holajan/DC.Construire.Tâches

maintenant nous configurons MSBuild pour utiliser cette tâche et définissons FileVersion et AssemblyVersion propriétés. Dans. fichier csproj il ressemble à ceci:

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

important things here:

  • Mentionné UsingTask importations GetCurrentBuildVersion tâche de DC.Construire.Tâche.dll . Il suppose que ce fichier dll est situé sur le répertoire parent de votre .fichier csproj.
  • notre BeforeBuildActionsProject1 cible que les appels tâche doit avoir un nom unique par projet dans le cas où nous avons plus de projets dans la solution qui appelle getcurrentbuildversion tâche.

l'avantage de cette solution est qu'elle fonctionne non seulement à partir de constructions sur le serveur de construction, mais aussi dans les constructions manuelles à partir de dotnet build ou Visual Studio.

12
répondu HolaJan 2017-04-15 13:00:15

ces valeurs sont maintenant définies dans le fichier .csproj :

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

ce sont les mêmes valeurs que vous voyez si vous allez dans l'onglet Package dans les paramètres du projet. Bien que je ne pense pas que vous puissiez utiliser * pour auto-activer la version, ce que vous pouvez faire est d'introduire une étape de post-traitement qui remplace les versions pour vous (par exemple dans le cadre de votre intégration continue).

8
répondu Gigi 2017-03-25 18:08:04

dotnet build /p:AssemblyVersion=1.2.3.4

je répond: "quelqu'un a compris comment le contrôle de version .NET de Base (ou .NETStandard d'ailleurs."J'ai trouvé cette question en essayant de résoudre ce problème dans le contexte d'une construction de CI. Je voulais régler la version d'assemblage sur le numéro de construction CI.

7
répondu Chris McKenzie 2017-10-30 17:15:21

j'ai fait un outil CLI simple pour le réglage .csproj .NET de Base les chaînes de version ici . Vous pouvez le combiner avec des outils comme GitVersion pour booster la version automatique pendant les constructions CI, si c'est ce que vous recherchez.

6
répondu Tagc 2017-04-03 21:28:52

j'ai accepté la réponse ci-dessus parce que @Gigi est correct (dès maintenant) mais j'ai été ennuyé et j'ai trouvé les Scripts PowerShell suivants.

J'ai D'abord le script dans mon dossier solution (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)

j'ai ajouté ceci au fichier 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>

même à travers son ensemble pour être un PreBuildEvent, le fait est que les numéros de version ne sont pas mis à jour jusqu'à ce que le fichier a été chargé dans mémoire donc le numéro de version ne reflètera pas avant la prochaine compilation. En fait, vous pourriez le changer pour un événement PostBuildEvent et il aurait le même effet.

j'ai aussi créé les deux scripts suivants: (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)
5
répondu Jason H 2018-08-17 16:23:01

pour activer la version de votre .net Core / .Net quel que soit le projet basé sur votre configuration GIT, en utilisant les tags/describe fonctionnalité de git.

j'ai utilisé un Prébuild.cible.fichier xml qui se trouve dans le dossier racine du projet et inclus dans le fichier csproj comme:

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

utilisez la balise" Generateassemblyinfo " pour désactiver la génération automatique d'informations d'assemblage.

puis le Paquetage.cible.xml générera une Infoassemblée commune.fichier cs où vous pouvez inclure les balises de version que vous voulez basé sur votre version GIT

NOTE: j'ai trouvé les Prébuilds.cible.xml ailleurs, donc pas la peine de nettoyer .)

Le Paquetage.cible.fichier 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>

modifier: si vous construisez en utilisant MSBUILD le

 $(SolutionDir)

peut vous causer des problèmes, utilisez

 $(ProjectDir)

au lieu de

3
répondu Tue Skeltved 2017-10-09 11:06:19

L'extension des Versions automatiques pour Visual Studio prend maintenant en charge L'auto-implémentation .Net Core et .Net Standard dans une interface utilisateur simple.

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

2
répondu madamission 2018-02-26 20:51:00

je pense que réponse de @joelsand est la bonne réponse pour définir le numéro de version pour dotnet core tournant sur VSTS

pour ajouter plus d'information pour cette réponse,

BUILD_BUILDNUMBER est en fait une variable prédéfinie .

il s'avère qu'il existe 2 versions de variable prédéfinie.

L'un est construit.xxxx, L'autre est BUILD_XXXX.

vous ne pouvez utiliser Environment Variable Name que dans cproj.

1
répondu maxisam 2018-02-15 22:33:10

vous pouvez utiliser une fonction de propriété MSBuild pour définir le suffixe de version basé sur la date courante:

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

cela va produire un paquet avec un nom comme: nom du paquet.1.0.0-pre20180807-1711.nupkg .

plus de détails sur les fonctions de la propriété MSBuild: https://docs.microsoft.com/en-us/visualstudio/msbuild/property-functions

1
répondu Fabricio Godoy 2018-08-07 21:08:16

nous pouvons utiliser un paramètre spécial pour dotnet publish -- version-suffix 1.2.3

pour la version de fichier:

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

pour la version:

<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.
0
répondu zxxc 2018-09-10 15:15:38