Quali sono le differenze tra AssemblyVersion, AssemblyFileVersion e AssemblyInformationalVersion?


860

Esistono tre attributi della versione dell'assembly. Quali sono le differenze? Va bene se uso AssemblyVersione ignoro il resto?


MSDN dice:

  • AssemblyVersion :

    Specifica la versione dell'assembly attribuito.

  • AssemblyFileVersion :

    Indica a un compilatore di utilizzare un numero di versione specifico per la risorsa versione file Win32. Non è necessario che la versione del file Win32 corrisponda al numero di versione dell'assembly.

  • AssemblyInformationalVersion :

    Definisce ulteriori informazioni sulla versione per un manifest dell'assembly.


Questo è il seguito di Quali sono le migliori pratiche per l'utilizzo degli attributi di assieme?

Risposte:


907

AssemblyVersion

Dove verranno visualizzati gli altri assiemi che fanno riferimento al proprio assieme. Se questo numero cambia, altri assembly devono aggiornare i loro riferimenti al proprio assembly! Aggiorna questa versione solo se interrompe la compatibilità con le versioni precedenti. Il AssemblyVersionè richiesto.

Uso il formato: major.minor . Ciò comporterebbe:

[assembly: AssemblyVersion("1.0")]

Se segui rigorosamente SemVer, ciò significa che esegui l' aggiornamento solo quando le modifiche principali , quindi 1.0, 2.0, 3.0, ecc.

AssemblyFileVersion

Utilizzato per la distribuzione. È possibile aumentare questo numero per ogni distribuzione. È utilizzato dai programmi di installazione. Usalo per contrassegnare gli assembly che hanno lo stesso AssemblyVersion, ma che sono generati da build diverse.

In Windows, può essere visualizzato nelle proprietà del file.

AssemblyFileVersion è facoltativo. Se non indicato, viene utilizzata AssemblyVersion.

Uso il formato: major.minor.patch.build , dove seguo SemVer per le prime tre parti e utilizzo il numero di build del server di build per l'ultima parte (0 per build locale). Ciò comporterebbe:

[assembly: AssemblyFileVersion("1.3.2.254")]

Ricorda che System.Version nomina queste parti come major.minor.build.revision!

AssemblyInformationalVersion

La versione del prodotto dell'assieme. Questa è la versione che useresti quando parli con i clienti o per la visualizzazione sul tuo sito web. Questa versione può essere una stringa, come " 1.0 Release Candidate ".

Il AssemblyInformationalVersionè opzionale. Se non indicato, viene utilizzato AssemblyFileVersion.

Uso il formato: major.minor [.patch] [revisione come stringa] . Ciò comporterebbe:

[assembly: AssemblyInformationalVersion("1.0 RC1")]

4
Per AssemblyFileVersion, "Se possibile, lascia che sia generato da MSBuild" - Perché? Hai solo spiegato un buon motivo per controllarlo manualmente :)
mo.

3
L'avvertimento sul formato AssemblyInformationalVersion esiste ancora oggi in VS2010 (21 maggio 2013) e il tuo link è morto.
reinierpost,

22
Sfortunatamente la Classe di Versione definisce major.minor[.build[.revision]]e non major.minor.revision.buildcosì nella risposta data i numeri di build e revisione verrebbero scambiati se si usassero le proprietà della classe o System.Reflection.Assembly.GetExecutingAssembly().GetName().Versionper rilevare i numeri di build e revisione.
thinkOfaNumber

9
@thinkOfaNumber I tuoi diritti sulla classe di versione, ma questo è il modo Microsoft di versionare. Personalmente penso che sia strano non avere il numero di build alla fine ed è per questo che ho solo messo il mio formato come esempio, basato sul Semantic Versioning . Sei libero di usare il modo Microsoft o il tuo modo naturalmente.
Rémy van Duijkeren,

6
Va notato che per AssemblyInformationalVersion, se omesso, AssemblyFileVersionviene utilizzato. Quindi AssemblyVersion se entrambi vengono omessi.
Drazen Bjelovuk,

588

Il controllo delle versioni degli assembly in .NET può essere una prospettiva confusa dato che al momento esistono almeno tre modi per specificare una versione per il proprio assembly.

Ecco i tre principali attributi di assemblaggio relativi alla versione:

// Assembly mscorlib, Version 2.0.0.0
[assembly: AssemblyFileVersion("2.0.50727.3521")]
[assembly: AssemblyInformationalVersion("2.0.50727.3521")]
[assembly: AssemblyVersion("2.0.0.0")]

Per convenzione, le quattro parti della versione sono indicati come la versione principale , la versione minore , Costruire , e di revisione .

L' AssemblyFileVersionobiettivo è identificare in modo univoco una build del singolo assieme

In genere, imposti manualmente il file AssemblyFileVersion principale e secondario in modo che rifletta la versione dell'assembly, quindi aumenti la build e / o la revisione ogni volta che il sistema di compilazione compila l'assembly. AssemblyFileVersion dovrebbe consentire di identificare in modo univoco una build dell'assembly, in modo da poterlo utilizzare come punto di partenza per il debug di eventuali problemi.

Nel mio progetto attuale, il server di build codifica il numero dell'elenco modifiche dal nostro repository di controllo del codice sorgente nelle parti Build e Revision di AssemblyFileVersion. Questo ci consente di mappare direttamente da un assembly al suo codice sorgente, per qualsiasi assembly generato dal server di compilazione (senza dover utilizzare etichette o rami nel controllo del codice sorgente o conservare manualmente i record delle versioni rilasciate).

Questo numero di versione è archiviato nella risorsa versione Win32 e può essere visualizzato quando si visualizzano le pagine delle proprietà di Esplora risorse per l'assembly.

Al CLR non interessa né esamina AssemblyFileVersion.

L' AssemblyInformationalVersionobiettivo è rappresentare la versione dell'intero prodotto

AssemblyInformationalVersion ha lo scopo di consentire un versioning coerente dell'intero prodotto, che può consistere in numerosi assembly con versione indipendente, forse con politiche di versioning diverse e potenzialmente sviluppati da team diversi.

“Ad esempio, la versione 2.0 di un prodotto potrebbe contenere diversi assiemi; uno di questi assembly è contrassegnato come versione 1.0 poiché è un nuovo assembly che non è stato fornito nella versione 1.0 dello stesso prodotto. In genere, si impostano le parti principali e secondarie di questo numero di versione per rappresentare la versione pubblica del prodotto. Quindi si aumentano le parti di costruzione e revisione ogni volta che si confeziona un prodotto completo con tutti i suoi assiemi. ” - Jeffrey Richter, [CLR via C # (Seconda Edizione)] p. 57

Il CLR non si preoccupa né esamina la AssemblyInformationalVersion.

L' AssemblyVersionè l'unica versione cure CLR circa (ma si preoccupa per l'intero AssemblyVersion)

AssemblyVersion viene utilizzato da CLR per associarsi a assembly con un nome sicuro. È archiviato nella tabella dei metadati manifest di AssemblyDef dell'assembly creato e nella tabella AssemblyRef di qualsiasi assembly che fa riferimento a esso.

Questo è molto importante, perché significa che quando si fa riferimento a un assembly con un nome sicuro, si è strettamente legati a una specifica AssemblyVersion di tale assembly. L'intera AssemblyVersion deve essere una corrispondenza esatta affinché l'associazione abbia esito positivo. Ad esempio, se si fa riferimento alla versione 1.0.0.0 di un assembly con nome sicuro in fase di compilazione, ma solo la versione 1.0.0.1 di tale assembly è disponibile in fase di esecuzione, l'associazione non riuscirà! (Dovrai quindi ovviare a questo usando il reindirizzamento del binding dell'assieme .)

Confusione sul fatto che l'intero AssemblyVersiondebba corrispondere. (Sì, lo fa.)

C'è un po 'di confusione sul fatto che l'intera AssemblyVersion debba essere una corrispondenza esatta per poter caricare un assembly. Alcune persone hanno la falsa convinzione che solo le parti principali e minori dell'AssembleaVersione devono abbinare per avere successo. Questo è un presupposto ragionevole, tuttavia alla fine non è corretto (a partire da .NET 3.5) ed è banale verificarlo per la propria versione del CLR. Basta eseguire questo codice di esempio .

Sulla mia macchina il secondo carico di assemblaggio fallisce e le ultime due righe del registro di fusione chiariscono perfettamente perché:

.NET Framework Version: 2.0.50727.3521
---
Attempting to load assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f
Successfully loaded assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f
---
Attempting to load assembly: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
Assembly binding for  failed:
System.IO.FileLoadException: Could not load file or assembly 'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, 
PublicKeyToken=0b3305902db7183f' or one of its dependencies. The located assembly's manifest definition 
does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f'

=== Pre-bind state information ===
LOG: User = Phoenix\Dani
LOG: DisplayName = Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
 (Fully-specified)
LOG: Appbase = [...]
LOG: Initial PrivatePath = NULL
Calling assembly : AssemblyBinding, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v2.0.50727\config\machine.config.
LOG: Post-policy reference: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
LOG: Attempting download of new URL [...].
WRN: Comparing the assembly name resulted in the mismatch: Revision Number
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.

Penso che la fonte di questa confusione sia probabilmente perché Microsoft originariamente intendeva essere un po 'più indulgente in questo stretto abbinamento di AssemblyVersion completo, abbinando solo le parti della versione Major e Minor:

"Quando si carica un assieme, il CLR troverà automaticamente l'ultima versione di manutenzione installata che corrisponde alla versione principale / secondaria dell'assieme richiesto." - Jeffrey Richter, [CLR via C # (Seconda Edizione)] p. 56

Questo era il comportamento in Beta 1 del CLR 1.0, tuttavia questa funzionalità è stata rimossa prima della versione 1.0 e non è riuscita a risalire in .NET 2.0:

“Nota: ho appena descritto come dovresti pensare ai numeri di versione. Sfortunatamente, il CLR non tratta i numeri di versione in questo modo. [In .NET 2.0], il CLR considera un numero di versione come un valore opaco e se un assembly dipende dalla versione 1.2.3.4 di un altro assembly, il CLR tenta di caricare solo la versione 1.2.3.4 (a meno che non sia presente un reindirizzamento vincolante ). Tuttavia, Microsoft ha in programma di modificare il caricatore del CLR in una versione futura in modo che carichi l'ultimo build / revisione per una determinata versione principale / secondaria di un assembly . Ad esempio, su una versione futura del CLR, se il caricatore sta cercando di trovare la versione 1.2.3.4 di un assieme ed esiste la versione 1.2.5.0, il caricatore con preleva automaticamente l'ultima versione di manutenzione. Questa sarà una modifica molto gradita al caricatore del CLR - io per uno non vedo l'ora ”. - Jeffrey Richter, [CLR via C # (Seconda Edizione)] p. 164 (Enfasi mia)

Poiché questo cambiamento non è ancora stato implementato, penso che sia sicuro supporre che Microsoft abbia rinviato questo intento, ed è forse troppo tardi per cambiarlo ora. Ho provato a cercare sul Web per scoprire cosa è successo con questi piani, ma non sono riuscito a trovare alcuna risposta. Volevo ancora arrivare fino in fondo.

Così ho mandato un'e-mail a Jeff Richter e gli ho chiesto direttamente: ho pensato che se qualcuno avesse saputo cosa sarebbe successo, sarebbe stato lui.

Ha risposto entro 12 ore, un sabato mattina non meno, e ha chiarito che il caricatore .NET 1.0 Beta 1 ha implementato questo meccanismo di "roll-forward automatico" per raccogliere l'ultima build disponibile e revisione di un assembly, ma questo comportamento era ripristinato prima della spedizione di .NET 1.0. In seguito è stato progettato per rilanciare questo, ma non è arrivato prima della spedizione del CLR 2.0. Poi è arrivata Silverlight, che ha avuto la priorità per il team CLR, quindi questa funzionalità è stata ulteriormente ritardata. Nel frattempo, la maggior parte delle persone che erano in giro ai tempi di CLR 1.0 Beta 1 sono passate da allora, quindi è improbabile che questo vedrà la luce del giorno, nonostante tutto il duro lavoro che era già stato messo dentro.

Il comportamento attuale, a quanto pare, è qui per rimanere.

Vale anche la pena notare dalla mia discussione con Jeff che AssemblyFileVersion è stato aggiunto solo dopo la rimozione del meccanismo di "roll-forward automatico" - perché dopo 1.0 Beta 1, qualsiasi modifica a AssemblyVersion è stata una svolta per i tuoi clienti, quindi da nessuna parte per memorizzare in sicurezza il numero di build. AssemblyFileVersion è un rifugio sicuro, poiché non viene mai esaminato automaticamente dal CLR. Forse è più chiaro in quel modo, con due numeri di versione separati, con significati separati, piuttosto che cercare di fare quella separazione tra le parti Major / Minor (break) e Build / Revision (non break) di AssemblyVersion.

La linea di fondo: pensa attentamente quando cambi il tuo AssemblyVersion

La morale è che se stai spedendo assemblee a cui faranno riferimento altri sviluppatori, devi fare molta attenzione quando cambi (e non cambi) la AssemblyVersion di quegli assemblaggi. Eventuali modifiche a AssemblyVersion significheranno che gli sviluppatori di applicazioni dovranno ricompilare la nuova versione (per aggiornare quelle voci di AssemblyRef) o utilizzare i reindirizzamenti dell'associazione dell'assieme per sostituire manualmente l'associazione.

  • Non modificare AssemblyVersion per una versione di manutenzione che deve essere compatibile con le versioni precedenti.
  • Non cambiare l'AssemblyVersion per un rilascio che si sa ha cambiamenti di rottura.

Dai un'occhiata agli attributi della versione su mscorlib:

// Assembly mscorlib, Version 2.0.0.0
[assembly: AssemblyFileVersion("2.0.50727.3521")]
[assembly: AssemblyInformationalVersion("2.0.50727.3521")]
[assembly: AssemblyVersion("2.0.0.0")]

Nota che è AssemblyFileVersion che contiene tutte le informazioni di manutenzione interessanti (è la parte Revision di questa versione che ti dice su quale Service Pack stai usando), nel frattempo AssemblyVersion è riparato su un vecchio noioso 2.0.0.0. Qualsiasi modifica a AssemblyVersion costringerebbe ogni applicazione .NET che fa riferimento a mscorlib.dll a ricompilarsi con la nuova versione!


9
Bella risposta. Penso che il punto più importante che hai sollevato - e che cosa MS dovrebbe esplicitamente raccomandare - è apportare modifiche a AssemblyVersion se e solo se la nuova versione rompe la compatibilità con le versioni precedenti.
mwolfe02,

1
Una delle domande che mi pongo ripetutamente è quando dovrei cambiare ciascuno di questi numeri di versione, i tuoi punti elenco su AssemblyVersion hanno aggiunto una buona chiarezza a questo e l'intera risposta è stata una lettura interessante.
RyanfaeScotland,

Vedo molte risposte che spiegano i concetti alla base di queste tre cose. Ma come si collegano ai numeri di versione modificabili nelle proprietà del progetto? Quando si fa clic su Informazioni sull'assieme ... è possibile modificare due versioni. E cambiando la versione dell'assieme si cambia la cartella in cui si trova user.config, e cambiando la versione del file si cambia il numero di versione mostrato quando si fa clic con il pulsante destro del mouse sul file exe e si passa alle sue proprietà. Quindi, in che modo questi due numeri di versione corrispondono a AssemblyVersion, AssemblyFileVersion e AssemblyInformationalVersion?
Kyle Delaney,

Il link al post sul blog che hai scritto originariamente dà un 404. C'è una nuova posizione per quello?
Rob K,

@RobK: Ah, scuse. Quel sito web è inattivo, ma l'intero contenuto del post del blog è riprodotto nella risposta in modo da non perdere nulla. Ora rimuoverò il link non funzionante.
Daniel Fortunov,

43

AssemblyVersionpraticamente rimane interno a .NET, mentre AssemblyFileVersionè quello che vede Windows. Se vai alle proprietà di un assembly seduto in una directory e passi alla scheda della versione, AssemblyFileVersionè quello che vedrai in alto. Se ordini i file per versione, questo è ciò che viene utilizzato da Explorer.

Le AssemblyInformationalVersionmappe alla "versione del prodotto" ed è pensato per essere puramente "usato dall'uomo".

AssemblyVersionè sicuramente il più importante, ma non salterei AssemblyFileVersionneanche io . Se non lo fornisci AssemblyInformationalVersion, il compilatore lo aggiunge per te togliendo il pezzo di "revisione" del tuo numero di versione e lasciando major.minor.build.


23

AssemblyInformationalVersione AssemblyFileVersionvengono visualizzati quando si visualizzano le informazioni "Versione" su un file tramite Esplora risorse visualizzando le proprietà del file. Questi attributi vengono effettivamente compilati in una VERSION_INFOrisorsa creata dal compilatore.

AssemblyInformationalVersion è il valore "Versione prodotto". AssemblyFileVersionè il valore "Versione file".

Il AssemblyVersionè specifico per NET assembly ed è usato dal NET assembly loader sapere quale versione di un assieme di carico / bind in fase di esecuzione.

Di questi, l'unico che è assolutamente richiesto da .NET è l' AssemblyVersionattributo. Sfortunatamente può anche causare la maggior parte dei problemi quando cambia in modo indiscriminato, specialmente se sei forte nel nominare i tuoi assiemi.


9

Per mantenere aggiornata questa domanda, vale la pena sottolineare che AssemblyInformationalVersionviene utilizzato da NuGet e riflette la versione del pacchetto incluso qualsiasi suffisso pre-release.

Ad esempio, AssemblyVersion di 1.0.3. * Impacchettato con il core aspnet dotnet-cli

dotnet pack --version-suffix ci-7 src/MyProject

Produce un pacchetto con la versione 1.0.3-ci-7 che è possibile controllare con la riflessione usando:

CustomAttributeExtensions.GetCustomAttribute<AssemblyInformationalVersionAttribute>(asm);

7

Vale la pena notare alcune altre cose:

1) Come mostrato nella finestra di dialogo Proprietà di Esplora risorse per il file assembly generato, esistono due posizioni denominate "Versione file". Quello visualizzato nell'intestazione della finestra di dialogo mostra AssemblyVersion, non AssemblyFileVersion.

Nella sezione Altre informazioni sulla versione, c'è un altro elemento chiamato "Versione file". Qui puoi vedere cosa è stato inserito come AssemblyFileVersion.

2) AssemblyFileVersion è solo testo. Non deve conformarsi alle restrizioni dello schema di numerazione di AssemblyVersion (<build> <65K, ad es.). Può essere 3.2. <Testo tag rilascio>. <datetime>, se lo desideri. Il tuo sistema di compilazione dovrà compilare i token.

Inoltre, non è soggetto alla sostituzione dei caratteri jolly che AssemblyVersion è. Se hai solo un valore di "3.0.1. *" In AssemblyInfo.cs, questo è esattamente ciò che verrà mostrato nell'elemento Informazioni sulla versione-> Versione file.

3) Non conosco l'impatto su un programma di installazione dell'uso di qualcosa di diverso dai numeri di versione dei file numerici, però.


2

Quando viene modificata la AssemblyVersion di un assembly, se ha un nome sicuro, gli assembly di riferimento devono essere ricompilati, altrimenti l'assembly non viene caricato! Se non ha un nome sicuro, se non viene aggiunto esplicitamente al file di progetto, non verrà copiato nella directory di output durante la compilazione, quindi potresti perdere alcuni assiemi, specialmente dopo aver pulito la directory di output.


Questo è molto interessante! Potresti elaborare bit sulla parte "non verrà copiata nella directory di output"? Forse un collegamento a dove viene definito questo comportamento. Non ho mai capito perché alcune dipendenze indirette venivano copiate a volte, ma non sempre. Questo deve essere correlato al 100% ad esso.
julealgon,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.