web-dev-qa-db-fra.com

Comment avoir un numéro de version incrémentant automatiquement (Visual Studio)?

Je veux stocker un ensemble d'entiers qui s'incrémentent automatiquement au moment de la construction:

int MajorVersion = 0;
int MinorVersion = 1;
int Revision = 92;

Lorsque je compile, il s'incrémente automatiquement Revision. Lorsque je construis le projet d'installation, il incrémente MinorVersion (je peux le faire manuellement). MajorVersion ne serait incrémenté que manuellement.

Ensuite, je pourrais afficher un numéro de version dans le menu Aide/A propos de l'utilisateur sous la forme suivante:

 Version: 0.1.92 

Comment cela peut il etre accompli?

Cette question demande non seulement comment avoir un numéro de version auto-incrémenté, mais aussi comment l'utiliser dans le code, ce qui est une réponse plus complète que d'autres.

441
esac

Si vous ajoutez une classe AssemblyInfo à votre projet et modifiez l'attribut AssemblyVersion afin qu'il se termine par un astérisque, par exemple:

[Assembly: AssemblyVersion("2.10.*")]

Visual studio augmentera le nombre final pour vous selon ces règles (merci galets, je me suis trompé complètement!)

Pour référencer cette version dans le code afin de pouvoir l'afficher à l'utilisateur, vous utilisez la réflexion. Par exemple,

Version version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
DateTime buildDate = new DateTime(2000, 1, 1)
                        .AddDays(version.Build).AddSeconds(version.Revision * 2);
string displayableVersion = $"{version} ({buildDate})";

Deux pièges importants que vous devriez connaître

De @ ashes999:

Il est également intéressant de noter que si AssemblyVersion et AssemblyFileVersion sont spécifiés, vous ne le verrez pas sur votre fichier .exe.

De @ BrainSlugs83:

Définir uniquement le 4ème numéro sur * peut être incorrect, car la version ne sera pas toujours incrémentée. Le 3ème chiffre correspond au nombre de jours depuis l'an 2000 et le 4ème correspond au nombre de secondes écoulées depuis minuit (divisé par 2) [IT IS NOT RANDOM]. Ainsi, si vous construisez la solution tard dans la journée un jour et tôt dans la journée le lendemain, la version la plus récente porte un numéro de version antérieur. Je recommande de toujours utiliser X.Y.* au lieu de X.Y.Z.* parce que votre numéro de version augmentera TOUJOURS de cette façon.

578
Noel Kennedy

Vous pouvez utiliser le mécanisme de création de modèles T4 dans Visual Studio pour générer le code source requis à partir d'un simple fichier texte :

Je voulais configurer la génération d'informations de version pour certains projets .NET. J’ai étudié les options disponibles depuis longtemps, j’ai donc cherché dans l’espoir de trouver un moyen simple de le faire. Ce que j’ai trouvé n’était pas très encourageant: les gens écrivent des compléments Visual Studio et des tâches MsBuild personnalisées simplement pour obtenir un nombre entier (ok, peut-être deux). Cela semblait exagéré pour un petit projet personnel.

L'inspiration est venue d'une des discussions sur StackOverflow où quelqu'un a suggéré que les modèles T4 pourraient faire l'affaire. Et bien sûr, ils peuvent. La solution nécessite un effort minimal et aucune personnalisation du processus de génération ou de Visual Studio. Voici ce qu'il faut faire:

  1. Créez un fichier avec l'extension ".tt" et placez-y le modèle T4 qui générera les attributs AssemblyVersion et AssemblyFileVersion:
<#@ template language="C#" #>
// 
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.
// 

using System.Reflection;

[Assembly: AssemblyVersion("1.0.1.<#= this.RevisionNumber #>")]
[Assembly: AssemblyFileVersion("1.0.1.<#= this.RevisionNumber #>")]
<#+
    int RevisionNumber = (int)(DateTime.UtcNow - new DateTime(2010,1,1)).TotalDays;
#>

Vous devrez décider de l’algorithme de génération du numéro de version. Pour moi, il suffisait de générer automatiquement un numéro de révision défini sur le nombre de jours depuis le 1er janvier 2010. Comme vous pouvez le constater, la règle de génération de version est écrite en C # simple. Vous pouvez ainsi l'ajuster facilement à vos besoins. .

  1. Le fichier ci-dessus doit être placé dans l'un des projets. J'ai créé un nouveau projet avec uniquement ce fichier unique pour clarifier la technique de gestion des versions. Lorsque je construis ce projet (en fait, je n’ai même pas besoin de le construire: l’enregistrement du fichier suffit pour déclencher une action Visual Studio), le C # suivant est généré:
// 
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.
// 

using System.Reflection;

[Assembly: AssemblyVersion("1.0.1.113")]
[Assembly: AssemblyFileVersion("1.0.1.113")]

Oui, aujourd’hui, cela fait 113 jours depuis le 1er janvier 2010. Demain, le numéro de révision changera.

  1. La prochaine étape consiste à supprimer les attributs AssemblyVersion et AssemblyFileVersion des fichiers AssemblyInfo.cs de tous les projets devant partager les mêmes informations de version générées automatiquement. Au lieu de cela, choisissez "Ajouter un élément existant" pour chaque projet, accédez au dossier contenant le fichier de modèle T4, sélectionnez le fichier ".cs" correspondant et ajoutez-le sous forme de lien. Ça va faire!

Ce qui me plaît dans cette approche est qu’elle est légère (pas de tâches MsBuild personnalisées) et que les informations de version générées automatiquement ne sont pas ajoutées au contrôle de source. Et bien sûr, l’utilisation de C # pour l’algorithme de génération de version s’ouvre pour les algorithmes de toute complexité.

156
Robert Lewis

C’est mon implémentation de la suggestion T4 ... Cela incrémentera le numéro de construction chaque fois que vous construirez le projet, quelle que soit la configuration sélectionnée (par exemple, Debug | Release), et incrémentera le numéro de révision à chaque fois que vous ferez une version Release. Vous pouvez continuer à mettre à jour les numéros de version majeure et mineure via Application Informations sur l'assemblage ...

Pour expliquer plus en détail, ceci lira le fichier AssemblyInfo.cs existant et utilisera regex pour trouver les informations AssemblyVersion, puis incrémentera les numéros de révision et de construction en fonction des entrées de TextTransform.exe.

  1. Supprimez votre fichier AssemblyInfo.cs existant.
  2. Créez un fichier AssemblyInfo.tt à la place. Visual Studio doit créer AssemblyInfo.cs et le regrouper avec le fichier T4 après avoir enregistré le fichier T4.

    <#@ template debug="true" hostspecific="true" language="C#" #>
    <#@ output extension=".cs" #>
    <#@ import namespace="System.IO" #>
    <#@ import namespace="System.Text.RegularExpressions" #>
    <#
        string output = File.ReadAllText(this.Host.ResolvePath("AssemblyInfo.cs"));
        Regex pattern = new Regex("AssemblyVersion\\(\"(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<revision>\\d+)\\.(?<build>\\d+)\"\\)");
        MatchCollection matches = pattern.Matches(output);
        if( matches.Count == 1 )
        {
            major = Convert.ToInt32(matches[0].Groups["major"].Value);
            minor = Convert.ToInt32(matches[0].Groups["minor"].Value);
            build = Convert.ToInt32(matches[0].Groups["build"].Value) + 1;
            revision = Convert.ToInt32(matches[0].Groups["revision"].Value);
            if( this.Host.ResolveParameterValue("-","-","BuildConfiguration") == "Release" )
                revision++;
        }
    #>
    
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using System.Resources;
    
    // General Information
    [Assembly: AssemblyTitle("Insert title here")]
    [Assembly: AssemblyDescription("Insert description here")]
    [Assembly: AssemblyConfiguration("")]
    [Assembly: AssemblyCompany("Insert company here")]
    [Assembly: AssemblyProduct("Insert product here")]
    [Assembly: AssemblyCopyright("Insert copyright here")]
    [Assembly: AssemblyTrademark("Insert trademark here")]
    [Assembly: AssemblyCulture("")]
    
    // Version informationr(
    [Assembly: AssemblyVersion("<#= this.major #>.<#= this.minor #>.<#= this.revision #>.<#= this.build #>")]
    [Assembly: AssemblyFileVersion("<#= this.major #>.<#= this.minor #>.<#= this.revision #>.<#= this.build #>")]
    [Assembly: NeutralResourcesLanguageAttribute( "en-US" )]
    
    <#+
        int major = 1;
        int minor = 0;
        int revision = 0;
        int build = 0;
    #>
    
  3. Ajoutez ceci à votre événement pré-build:

    "%CommonProgramFiles(x86)%\Microsoft shared\TextTemplating\$(VisualStudioVersion)\TextTransform.exe" -a !!BuildConfiguration!$(Configuration) "$(ProjectDir)Properties\AssemblyInfo.tt"
    
42
Drew Chapin

Si vous insérez un astérisque pour la construction et la révision, visual studio utilise le nombre de jours écoulés depuis le 1er janvier 2000 comme numéro de build et le nombre de secondes depuis minuit divisé par 2 comme la révision.

Une solution BEAUCOUP mieux meilleure pour la vie est http://autobuildversion.codeplex.com/

Cela fonctionne comme un charme et c'est très flexible.

31
gideon

Voici le citation sur AssemblyInfo.cs de MSDN :

Vous pouvez spécifier toutes les valeurs ou accepter le numéro de construction par défaut, le numéro de révision ou les deux à l'aide d'un astérisque (). Par exemple, [Assembly: AssemblyVersion ("2.3.25.1")] indique 2 en tant que version principale, 3 en tant que version mineure, 25 en tant que numéro de version et 1 en tant que numéro de révision. Un numéro de version tel que [Assembly: AssemblyVersion ("1.2. ")] spécifie 1 en tant que version principale, 2 en tant que version mineure et accepte les numéros de construction et de révision par défaut. Un numéro de version tel que [Assembly: AssemblyVersion ("1.2.15. *")] Spécifie 1 en tant que version principale, 2 en tant que version mineure, 15 en tant que numéro de version et accepte le numéro de révision par défaut. Le numéro de build par défaut s'incrémente quotidiennement. Le numéro de révision par défaut est aléatoire

En pratique, cela signifie que si vous mettez un 1.1. * Dans les informations sur l’Assemblée, seul le numéro de la construction sera auto-incrémenté, et cela ne se produira pas après chaque construction, mais tous les jours. Le numéro de révision changera chaque version, mais de manière aléatoire, plutôt que de manière incrémentée.

C'est probablement suffisant pour la plupart des cas d'utilisation. Si ce n'est pas ce que vous cherchez, vous êtes obligé d'écrire un script qui incrémentera automatiquement le numéro de version à l'étape de pré-construction.

23
galets

Utiliser AssemblyInfo.cs

Créez le fichier dans App_Code: et complétez les informations suivantes ou utilisez Google pour d'autres possibilités d'attributs/propriétés.

AssemblyInfo.cs

using System.Reflection;

[Assembly: AssemblyDescription("Very useful stuff here.")]
[Assembly: AssemblyCompany("companyname")]
[Assembly: AssemblyCopyright("Copyright © me 2009")]
[Assembly: AssemblyProduct("NeatProduct")]
[Assembly: AssemblyVersion("1.1.*")]

AssemblyVersion étant la partie que vous recherchez vraiment.

Ensuite, si vous travaillez sur un site Web, dans une page ou un contrôle aspx, vous pouvez ajouter dans la balise <Page>, les éléments suivants:

CompilerOptions="<folderpath>\App_Code\AssemblyInfo.cs"

(remplacement de folderpath par la variable appropriée bien sûr).

Je ne crois pas que vous ayez besoin d'ajouter des options de compilation de quelque manière que ce soit pour les autres classes; Tous ceux de App_Code doivent recevoir les informations de version lorsqu'ils sont compilés.

J'espère que ça t'as aidé.

14
Micah Smith

Vous pouvez essayer d'utiliser pdateVersion de Matt Griffith . C'est assez vieux maintenant, mais ça marche bien. Pour l'utiliser, il vous suffit de configurer un événement de pré-génération pointant vers votre fichier AssemblyInfo.cs. L'application mettra à jour les numéros de version en conséquence, conformément aux arguments de la ligne de commande.

Comme l'application est open-source, j'ai également créé une version pour incrémenter le numéro de version au format (version majeure). (Version mineure). ([Année] [jour de l'année]). incrément). Plus d'informations à ce sujet et sur le code révisé sont disponibles sur l'entrée de mon blog, Numéros de version de l'Assemblée et .NET .

Mise à jour: j'ai mis le code de ma version modifiée de l'application UpdateVersion sur GitHub: https://github.com/munr/UpdateVersion

10
Mun
  • Star en version (comme "2.10.3. *") - c'est simple, mais les nombres sont trop grands

  • AutoBuildVersion - a fière allure, mais ça ne marche pas sur mon VS2010.

  • Le script de @ DrewChapin fonctionne, mais dans mon studio, je ne peux pas définir différents modes pour l'événement de pré-génération Debug et l'événement de pré-génération Release.

j'ai donc changé un peu le script ... commamd:

"%CommonProgramFiles(x86)%\Microsoft shared\TextTemplating\10.0\TextTransform.exe" -a !!$(ConfigurationName)!1 "$(ProjectDir)Properties\AssemblyInfo.tt"

et script (cela fonctionne avec les configurations "Debug" et "Release"):

<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ Assembly name="System.Windows.Forms" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#
    int incRevision = 1;
    int incBuild = 1;

    try { incRevision = Convert.ToInt32(this.Host.ResolveParameterValue("","","Debug"));} catch( Exception ) { incBuild=0; }
    try { incBuild = Convert.ToInt32(this.Host.ResolveParameterValue("","","Release")); } catch( Exception ) { incRevision=0; }
    try {
        string currentDirectory = Path.GetDirectoryName(Host.TemplateFile);
        string assemblyInfo = File.ReadAllText(Path.Combine(currentDirectory,"AssemblyInfo.cs"));
        Regex pattern = new Regex("AssemblyVersion\\(\"\\d+\\.\\d+\\.(?<revision>\\d+)\\.(?<build>\\d+)\"\\)");
        MatchCollection matches = pattern.Matches(assemblyInfo);
        revision = Convert.ToInt32(matches[0].Groups["revision"].Value) + incRevision;
        build = Convert.ToInt32(matches[0].Groups["build"].Value) + incBuild;
    }
    catch( Exception ) { }
#>
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an Assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an Assembly.
[Assembly: AssemblyTitle("Game engine. Keys: F2 (Debug trace), F4 (Fullscreen), Shift+Arrows (Move view). ")]
[Assembly: AssemblyProduct("Game engine")]
[Assembly: AssemblyDescription("My engine for game")]
[Assembly: AssemblyCompany("")]
[Assembly: AssemblyCopyright("Copyright © Name 2013")]
[Assembly: AssemblyTrademark("")]
[Assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this Assembly not visible
// to COM components.  If you need to access a type in this Assembly from
// COM, set the ComVisible attribute to true on that type. Only Windows
// assemblies support COM.
[Assembly: ComVisible(false)]

// On Windows, the following GUID is for the ID of the typelib if this
// project is exposed to COM. On other platforms, it unique identifies the
// title storage container when deploying this Assembly to the device.
[Assembly: Guid("00000000-0000-0000-0000-000000000000")]

// Version information for an Assembly consists of the following four values:
//
//      Major Version
//      Minor Version
//      Build Number
//      Revision
//
[Assembly: AssemblyVersion("0.1.<#= this.revision #>.<#= this.build #>")]
[Assembly: AssemblyFileVersion("0.1.<#= this.revision #>.<#= this.build #>")]

<#+
    int revision = 0;
    int build = 0;
#>
10
Dmi7ry

Vous pouvez faire un versioning plus avancé en utilisant des scripts de compilation tels que Build Versioning

2
Raymond