Quali sono le differenze tra AssemblyVersion, AssemblyFileVersion e AssemblyInformationalVersion?

StackOverflow https://stackoverflow.com/questions/64602

  •  09-06-2019
  •  | 
  •  

Domanda

Sono disponibili tre attributi della versione dell'assembly.Quali sono le differenze?Va bene se lo uso AssemblyVersion e ignorare il resto?


MSDN dice:

  • AssemblyVersion:

    Specifica la versione dell'assembly da attribuire.

  • AssemblyFileVersion:

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

  • AssemblyInformationalVersion:

    Definisce informazioni aggiuntive sulla versione per un manifesto dell'assembly.


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

È stato utile?

Soluzione

AssemblyVersion

Dove verranno visualizzati gli altri assembly che fanno riferimento al tuo assembly.Se questo numero cambia, altri gruppi devono aggiornare i loro riferimenti al tuo gruppo!IL AssemblyVersion è obbligatorio.

Io utilizzo il formato: maggiore.minore.Ciò comporterebbe:

[assembly: AssemblyVersion("1.0")]

AssemblyFileVersion

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

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

Se possibile, lascia che venga generato da MSBuild.AssemblyFileVersion è facoltativo.Se non fornito, viene utilizzato AssemblyVersion.

Io utilizzo il formato: major.minor.revision.build, dove utilizzo la revisione per la fase di sviluppo (Alpha, Beta, RC e RTM), service pack e hot fix.Ciò comporterebbe:

[assembly: AssemblyFileVersion("1.0.3100.1242")]

AssemblyInformationalVersion

La versione del prodotto dell'assembly.Questa è la versione che utilizzeresti quando parli con i clienti o per la visualizzazione sul tuo sito web.Questa versione può essere una stringa, come 'Candidato al rilascio 1.0'.

L'Analisi del Codice se ne lamenterà (CA2243) -- segnalato a Microsoft (non risolto in VS2013).

IL AssemblyInformationalVersion è facoltativo.Se non fornito, viene utilizzato AssemblyFileVersion.

Io utilizzo il formato: major.minor [revisione come stringa].Ciò comporterebbe:

[assembly: AssemblyInformationalVersion("1.0 RC1")]

Altri suggerimenti

Il controllo delle versioni degli assembly in .NET può creare confusione poiché attualmente esistono almeno tre modi per specificare una versione per l'assembly.

Ecco i tre principali attributi di assembly 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 denominate Versione principale, Versione minore, Costruire, E Revisione.

IL AssemblyFileVersion ha lo scopo di identificare in modo univoco una build del file assemblaggio individuale

In genere imposterai manualmente Major e Minor AssemblyFileVersion per riflettere la versione dell'assembly, quindi incrementerai Build e/o Revision ogni volta che il tuo sistema di build 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 abbiamo il server di compilazione che codifica il numero dell'elenco delle modifiche dal nostro repository di controllo del codice sorgente nelle parti di compilazione e revisione di AssemblyFileVersion.Ciò 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 della versione Win32 e può essere visualizzato quando si visualizzano le pagine delle proprietà di Esplora risorse per l'assembly.

Il CLR non si preoccupa né esamina AssemblyFileVersion.

IL AssemblyInformationalVersion è destinato a rappresentare la versione dell'intero prodotto

AssemblyInformationalVersion ha lo scopo di consentire un controllo delle versioni coerente dell'intero prodotto, che può consistere di molti assembly con versioni indipendenti, magari con politiche di controllo delle versioni diverse e potenzialmente sviluppati da team disparati.

“Ad esempio, la versione 2.0 di un prodotto potrebbe contenere diversi assembly;Uno di questi assiemi è contrassegnato come versione 1.0 poiché è un nuovo assembly che non è stato spedito nella versione 1.0 dello stesso prodotto.In genere, si impostano le parti principali e minori di questo numero di versione per rappresentare la versione pubblica del tuo prodotto.Quindi si aumentano le parti di build e revisioni ogni volta che si confezionano un prodotto completo con tutti i suoi assemblaggi. " - Jeffrey Richter, [CLR via C# (seconda edizione)] p.57

Il CLR non si preoccupa né esamina AssemblyInformationalVersion.

IL AssemblyVersion è l'unica versione che interessa a CLR (ma si preoccupa dell'intero file AssemblyVersion)

AssemblyVersion viene utilizzato da CLR per associarsi ad assembly con nomi sicuri.Viene archiviato nella tabella dei metadati manifest AssemblyDef dell'assembly creato e nella tabella AssemblyRef di qualsiasi assembly che fa riferimento ad 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 quell'assembly.L'intero AssemblyVersion deve corrispondere esattamente 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 in fase di esecuzione è disponibile solo la versione 1.0.0.1 di tale assembly, l'associazione avrà esito negativo!(Dovrai quindi aggirare questo problema utilizzando Reindirizzamento dell'associazione dell'assembly.)

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

C'è un po' di confusione sul fatto se l'intero AssemblyVersion debba avere una corrispondenza esatta affinché un assembly possa essere caricato.Alcune persone credono erroneamente che solo le parti Major e Minor di AssemblyVersion debbano corrispondere affinché l'associazione abbia esito positivo.Si tratta di un presupposto sensato, tuttavia in definitiva non è corretto (a partire da .NET 3.5) ed è banale verificarlo per la propria versione di CLR.Esegui e basta questo codice di esempio.

Sulla mia macchina il secondo caricamento dell'assemblaggio fallisce e le ultime due righe del registro di fusione rendono perfettamente chiaro il motivo:

.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 l'origine di questa confusione sia probabilmente dovuta al fatto che Microsoft originariamente intendeva essere un po' più indulgente su questa corrispondenza rigorosa dell'intera AssemblyVersion, abbinando solo le parti della versione Maggiore e Minore:

"Quando si carica un gruppo, il CLR troverà automaticamente l'ultima versione di manutenzione installata che corrisponde alla versione maggiore/minore dell'assembly richiesto." - Jeffrey Richter, [CLR via C# (seconda edizione)] p.56

Questo era il comportamento nella Beta 1 del CLR 1.0, tuttavia questa funzionalità è stata rimossa prima del rilascio 1.0 e non è riuscita a riemergere 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 tratta un numero di versione come un valore opaco e se un assieme 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 in atto un reindirizzamento vincolante ).Tuttavia, Microsoft ha in programma di modificare il caricatore del CLR in una versione futura in modo da caricare l'ultima build/revisione per una data versione maggiore/minore di un assieme.Ad esempio, su una versione futura del CLR, se il caricatore sta cercando di trovare la versione 1.2.3.4 di un assembly e la versione 1.2.5.0 esiste, il caricatore con ripresa automaticamente l'ultima versione di manutenzione.Questo 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 mio)

Poiché questo cambiamento non è stato ancora implementato, penso che sia lecito ritenere che Microsoft abbia fatto marcia indietro su questo intento, e forse è troppo tardi per cambiare la situazione ora.Ho provato a cercare sul Web per scoprire cosa è successo con questi piani, ma non sono riuscito a trovare alcuna risposta.Volevo ancora andare a fondo della questione.

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

Ha risposto entro 12 ore, nientemeno che un sabato mattina, e ha chiarito che il caricatore .NET 1.0 Beta 1 implementava questo meccanismo di "roll forward automatico" per raccogliere l'ultima build e revisione disponibile di un assembly, ma questo comportamento era ripristinato prima della spedizione di .NET 1.0.Successivamente si intendeva ripristinarlo, ma non ce l'ha fatta prima della spedizione del CLR 2.0.Poi è arrivato 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 da allora sono andate avanti, quindi è improbabile che questo veda la luce, nonostante tutto il duro lavoro che è già stato fatto.

Il comportamento attuale, a quanto pare, è destinato a durare.

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 la 1.0 Beta 1, qualsiasi modifica a AssemblyVersion era una modifica decisiva per i vostri clienti, quindi c'era nessun posto dove archiviare in modo sicuro il numero di build.AssemblyFileVersion è quel rifugio sicuro, poiché non viene mai esaminato automaticamente dal CLR.Forse è più chiaro in questo modo, avendo due numeri di versione separati, con significati separati, piuttosto che cercare di fare quella separazione tra le parti Maggiore/Minore (di rottura) e le parti Build/Revision (non di rottura) di AssemblyVersion.

La linea di fondo:Pensa attentamente a quando cambi il tuo AssemblyVersion

La morale è che se stai spedendo assembly a cui faranno riferimento altri sviluppatori, devi prestare estrema attenzione a quando modifichi (e non) la AssemblyVersion di tali assembly.Qualsiasi modifica a AssemblyVersion significherà che gli sviluppatori dell'applicazione dovranno ricompilare con la nuova versione (per aggiornare le voci AssemblyRef) o utilizzare reindirizzamenti di associazione dell'assembly per sovrascrivere manualmente l'associazione.

  • Non modificare AssemblyVersion per una versione di manutenzione destinata a essere compatibile con le versioni precedenti.
  • Fare modificare AssemblyVersion per una versione che contiene modifiche importanti.

Dai un'altra 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 ti trovi), mentre AssemblyVersion è fissato al noioso vecchio 2.0.0.0.Qualsiasi modifica a AssemblyVersion costringerebbe ogni applicazione .NET che fa riferimento a mscorlib.dll a ricompilare con la nuova versione!

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

IL AssemblyInformationalVersion corrisponde alla "Versione del prodotto" ed è destinato ad essere puramente "utilizzato dall'uomo".

AssemblyVersion è sicuramente il più importante, ma non lo salterei AssemblyFileVersion, O.Se non fornisci AssemblyInformationalVersion, il compilatore lo aggiunge per te rimuovendo la parte "revisione" del numero di versione e lasciando major.minor.build.

AssemblyInformationalVersion E AssemblyFileVersion vengono visualizzati quando si visualizzano le informazioni sulla "Versione" su un file tramite Esplora risorse visualizzando le proprietà del file.Questi attributi vengono effettivamente compilati in a VERSION_INFO risorsa creata dal compilatore.

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

IL AssemblyVersion è specifico degli assembly .NET e viene utilizzato dal caricatore di assembly .NET per sapere quale versione di un assembly caricare/associare in fase di esecuzione.

Di questi, l'unico assolutamente richiesto da .NET è il AssemblyVersion attributo.Sfortunatamente può anche causare la maggior parte dei problemi quando cambia indiscriminatamente, soprattutto se sei forte nel nominare i tuoi assembly.

Per mantenere attuale questa domanda vale la pena sottolinearlo AssemblyInformationalVersion viene utilizzato da NuGet e riflette il file versione del pacchetto incluso qualsiasi suffisso pre-release.

Ad esempio, una AssemblyVersion di 1.0.3.* confezionata con asp.net core dotnet-cli

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

Produce un pacchetto con la versione 1.0.3-ci-7 che puoi ispezionare con la riflessione usando:

CustomAttributeExtensions.GetCustomAttribute<AssemblyInformationalVersionAttribute>(asm);

Vale la pena notare alcune altre cose:

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

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

2) AssemblyFileVersion è solo testo semplice.Non deve essere conforme alle restrizioni dello schema di numerazione di AssemblyVersion (<build> < 65K, ad esempio).Può essere 3.2.<release tag text>.<datetime>, se preferisci.Il tuo sistema di build dovrà compilare i token.

Inoltre, non è soggetto alla sostituzione dei caratteri jolly come invece è AssemblyVersion.Se hai solo il valore "3.0.1.*" in AssemblyInfo.cs, questo è esattamente ciò che verrà visualizzato nell'elemento Altre informazioni sulla versione->Versione file.

3) Tuttavia, non conosco l'impatto su un programma di installazione dell'utilizzo di qualcosa di diverso dai numeri di versione del file numerico.

Quando viene modificata l'assemblaggio di un assembly, se ha un nome forte, gli assiemi di riferimento devono essere ricompilati, altrimenti l'assemblaggio non si carica!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, pertanto potresti perdere assembly dipendenti, soprattutto dopo aver pulito la directory di output.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top