it-swarm.it

Quali sono le differenze tra AssemblyVersion, AssemblyFileVersion e AssemblyInformationalVersion?

Esistono tre attributi di versione Assembly. Quali sono le differenze? Va bene se uso AssemblyVersion e ignoro 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 versione file Win32. La versione del file Win32 non è richiesta per essere uguale al numero di versione dell'Assembly.

  • AssemblyInformationalVersion :

    Definisce ulteriori informazioni sulla versione per un manifest di Assembly.


Questo è un seguito a Quali sono le migliori pratiche per usare gli Attributi dell'Assembly?

824
Jakub Šturc

AssemblyVersion

Dove appariranno altri gruppi che fanno riferimento alla tua Assemblea. Se questo numero cambia, gli altri assembly devono aggiornare i loro riferimenti all'assembly! AssemblyVersion è richiesto.

Io uso il formato: major.minor . Ciò comporterebbe:

[Assembly: AssemblyVersion("1.0")]

AssemblyFileVersion

Utilizzato per la distribuzione. È possibile 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 diverse build.

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

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

Uso il formato: major.minor.revision.build , dove uso la revisione per lo stadio 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'Assemblea. 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 '.

L'analisi del codice si lamenterà (CA2243) - segnalato a Microsoft (non risolto in VS2013).

AssemblyInformationalVersion è facoltativo. Se non specificato, viene utilizzato AssemblyFileVersion.

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

[Assembly: AssemblyInformationalVersion("1.0 RC1")]
871

Il controllo delle versioni degli assembly in .NET può essere un prospetto confuso, dato che attualmente esistono almeno tre modi per specificare una versione per il proprio assieme.

Ecco i tre attributi dell'Assembly relativi alla versione principale:

// 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 indicate come Versione principale , Versione secondaria , Build , and Revision .

AssemblyFileVersion ha lo scopo di identificare in modo univoco una build dell'assembly individuale

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

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

Questo numero di versione è memorizzato nella risorsa versione Win32 e può essere visualizzato durante la visualizzazione delle pagine di proprietà di Esplora risorse per l'assieme.

Il CLR non si preoccupa né esamina AssemblyFileVersion.

AssemblyInformationalVersion è inteso a rappresentare la versione dell'intero prodotto

AssemblyInformationalVersion ha lo scopo di consentire il versioning coerente dell'intero prodotto, che può essere costituito da molti assembly con versioni indipendenti, forse con politiche di versioning diverse e potenzialmente sviluppati da team eterogenei.

"Ad esempio, la versione 2.0 di un prodotto potrebbe contenere diversi assembly; 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 maggiore e minore di questo numero di versione per rappresentare la versione pubblica del prodotto. Quindi incrementate le parti di compilazione e revisione ogni volta che impacchettate un prodotto completo con tutti i suoi assemblaggi. "- Jeffrey Richter, [CLR via C # (Seconda edizione)] p. 57

Il CLR non interessa né esamina AssemblyInformationalVersion.

AssemblyVersion è l'unica versione interessata al CLR (ma interessa l'intero AssemblyVersion)

AssemblyVersion viene utilizzato dal CLR per eseguire il binding a assembly fortemente denominati. È memorizzato nella tabella dei metadati manifest AssemblyDef dell'assembly compilato e nella tabella AssemblyRef di qualsiasi assembly che fa riferimento a esso.

Questo è molto importante, perché significa che quando si fa riferimento ad un Assemblea fortemente denominata, si è strettamente legati a una specifica AssemblyVersion di quell'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 un nome fortemente definito in fase di build, ma solo la versione 1.0.0.1 di quell'assembly è disponibile in fase di runtime, l'associazione fallirà! (Dovrai quindi aggirare questo problema usando Assembly Binding Redirection .)

Confusione se l'intero AssemblyVersion deve 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 sono convinte che solo le parti Major e Minor della versione Assembly debbano corrispondere affinché il binding abbia successo. Questa è un'ipotesi ragionevole, tuttavia è in definitiva non corretta (da .NET 3.5) ed è banale verificarlo per la versione del CLR. Basta eseguire questo codice di esempio .

Sulla mia macchina il secondo carico di Assembly fallisce e le ultime due righe del log 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 questo rigoroso abbinamento di AssemblyVersion completo, facendo corrispondere solo le parti delle versioni Major e Minor:

"Quando si carica un assieme, il CLR troverà automaticamente la versione di manutenzione installata più recente che corrisponde alla versione principale/secondaria dell'assembly richiesta." - Jeffrey Richter, [CLR via C # (Seconda edizione)] p. 56

Questo era il comportamento nella Beta 1 del CLR 1.0, tuttavia questa funzione è stata rimossa prima della versione 1.0 e non è riuscita a ri-superficie 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 dell'associazione) ). Tuttavia, Microsoft ha in programma di modificare il caricatore CLR in una versione futura in modo che carichi l'ultima versione/revisione per una determinata versione principale/secondaria di un assieme . Ad esempio, in una versione futura del CLR, se il programma di caricamento tenta di trovare la versione 1.2.3.4 di un assieme e la versione 1.2.5.0 esiste, il caricatore preleva automaticamente la versione di manutenzione più recente. Questo sarà un cambiamento molto gradito al caricatore del CLR - Io per primo non posso aspettare. "- Jeffrey Richter, [CLR via C # (Seconda edizione)] p. 164 (Enfasi mia)

Dato che questo cambiamento non è ancora stato implementato, penso che sia lecito supporre che Microsoft abbia fatto marcia indietro su 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 a fondo.

Così ho mandato una 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, di sabato mattina, e ha chiarito che il loader .NET 1.0 Beta 1 ha implementato questo meccanismo di "rollforward automatico" per raccogliere l'ultima build e revisione disponibile di un assembly, ma questo comportamento era ripristinato prima della distribuzione di .NET 1.0. In seguito è stato previsto di riattivare questo problema ma non è stato fatto prima che il CLR 2.0 sia stato spedito. Poi è arrivato Silverlight, che ha avuto la priorità per il team CLR, quindi questa funzionalità è stata ritardata ulteriormente. Nel frattempo, la maggior parte delle persone che erano nei giorni di CLR 1.0 Beta 1 sono andate avanti, quindi è improbabile che questo veda la luce del giorno, nonostante tutto il duro lavoro che era già stato fatto.

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

Vale anche la pena di 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 alla AssemblyVersion era un cambiamento irrisolto per i clienti, allora c'era da nessuna parte per memorizzare in modo sicuro il tuo numero di build. AssemblyFileVersion è quel rifugio sicuro, dal momento che 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 Major/Minor (breaking) e Build/Revision (non-breaking) della AssemblyVersion.

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

La morale è che se si spediscono gli assembly a cui altri sviluppatori faranno riferimento, è necessario essere estremamente cauti quando si esegue (e non si) la AssemblyVersion di quegli assembly. Eventuali modifiche a AssemblyVersion implicheranno che gli sviluppatori dell'applicazione dovranno ricompilare la nuova versione (per aggiornare le voci AssemblyRef) o utilizzare i reindirizzamenti dell'associazione Assembly per sovrascrivere manualmente l'associazione.

  • Non modificare la AssemblyVersion per una versione di manutenzione destinata a essere retrocompatibile.
  • Do cambia AssemblyVersion per un rilascio che sai ha delle modifiche di rottura.

Basta dare 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")]

Si noti che è AssemblyFileVersion che contiene tutte le informazioni di assistenza interessanti (è la parte Revisione di questa versione che ti dice su quale Service Pack si trova), mentre la AssemblyVersion è fissa su una noiosa versione 2.0.0.0. Qualsiasi modifica a AssemblyVersion costringerebbe ogni applicazione .NET a fare riferimento a mscorlib.dll per ricompilare la nuova versione!

570
Daniel Fortunov

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

AssemblyInformationalVersion esegue il mapping alla "Versione prodotto" ed è pensato per essere puramente "utilizzato dall'uomo".

AssemblyVersion è sicuramente il più importante, ma non salterò nemmeno AssemblyFileVersion. Se non si fornisce AssemblyInformationalVersion, il compilatore lo aggiunge eliminando la parte "revisione" del numero di versione e lasciando major.minor.build.

42
Bob King

AssemblyInformationalVersion e AssemblyFileVersion vengono visualizzati quando si visualizzano le informazioni sulla "Versione" su un file tramite Windows Explorer visualizzando le proprietà del file. Questi attributi vengono effettivamente compilati in una risorsa VERSION_INFO creata dal compilatore.

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

AssemblyVersion è specifico per gli assembly .NET e viene utilizzato dal caricatore di .NET Package per sapere quale versione di un assembly caricare/associare in fase di runtime.

Di questi, l'unico che è assolutamente richiesto da .NET è l'attributo AssemblyVersion. Sfortunatamente può anche causare il maggior numero di problemi quando cambia indiscriminatamente, specialmente se si ha un nome forte nei propri assembly.

21
Scott Dorman

Per mantenere questa domanda corrente, è importante evidenziare che AssemblyInformationalVersion è utilizzato da NuGet e riflette la versione del pacchetto incluso qualsiasi suffisso pre-rilascio.

Ad esempio una AssemblyVersion di 1.0.3. * Confezionato con il core dotnet-asp.net

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

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

CustomAttributeExtensions.GetCustomAttribute<AssemblyInformationalVersionAttribute>(asm);
8
KCD

Vale la pena notare alcune altre cose:

1) Come mostrato nella finestra di dialogo Proprietà di Esplora risorse per il file Assembly generato, ci sono due posti chiamati "Versione file". Quello visto nell'intestazione della finestra di dialogo mostra AssemblyVersion, non AssemblyFileVersion.

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

2) AssemblyFileVersion è semplicemente testo. Non deve conformarsi alle restrizioni dello schema di numerazione eseguite da AssemblyVersion (<build> <65K, ad es.). Può essere 3.2. <Rilascia tag text>. <Datetime>, se lo desideri. Il tuo sistema di costruzione dovrà compilare i token.

Inoltre, non è soggetto alla sostituzione di caratteri jolly che sia AssemblyVersion. Se hai solo un valore di "3.0.1. *" In AssemblyInfo.cs, questo è esattamente ciò che verrà mostrato nell'elemento Other information-> File Version element.

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

7
DavidM

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 in modo da poter perdere gli assembly dipendenti, specialmente dopo aver pulito la directory di output.

2
linquize