Was sind die Unterschiede zwischen AssemblyVersion, AssemblyFileVersion und AssemblyInformationalVersion?

Es gibt drei Assemblyversionsattribute. Was sind Unterschiede? Ist es in Ordnung, wenn ich AssemblyVersion und den Rest ignoriere?


MSDN sagt:

  • assemblyversion :

    Gibt die Version der Assembly an, die zugeordnet wird.

  • AssemblyFileVersion :

    Weist einen Compiler an, eine bestimmte Versionsnummer für die Win32-Dateiversionsressource zu verwenden. Die Win32-Dateiversion muss nicht mit der Versionsnummer der Assembly übereinstimmen.

  • AssemblyInformationaleVersion :

    Definiert zusätzliche Versionsinformationen für ein Assemblymanifest.


Dies ist ein Follow-up zu Was sind die besten Methoden zur Verwendung von Assembly-Attributen?

AssemblyVersion

Wo andere Baugruppen, die auf Ihre Baugruppe verweisen, aussehen werden. Ändert sich diese Zahl, müssen andere Baugruppen ihre Referenzen auf Ihre Baugruppe aktualisieren! Die AssemblyVersion ist erforderlich.

Ich benutze das Format: major.minor . Dies würde zu folgenden Ergebnissen führen:

 [assembly: AssemblyVersion("1.0")] 

AssemblyFileVersion

Wird für die Bereitstellung verwendet. Sie können diese Anzahl für jede Bereitstellung erhöhen. Es wird von Setup-Programmen verwendet. Verwenden Sie es zum Markieren von Assemblys mit derselben AssemblyVersion , die jedoch aus verschiedenen Builds generiert werden.

In Windows kann es in den Dateieigenschaften angezeigt werden.

Wenn möglich, lass es von MSBuild generiert werden. Die AssemblyFileVersion ist optional. Wenn nicht angegeben, wird AssemblyVersion verwendet.

Ich benutze das Format: major.minor.revision.build , wo ich eine Revision für die Entwicklungsphase (Alpha, Beta, RC und RTM), Service Packs und Hotfixes verwende. Dies würde zu folgenden Ergebnissen führen:

 [assembly: AssemblyFileVersion("1.0.3100.1242")] 

AssemblyInformationaleVersion

Die Produktversion der Baugruppe. Dies ist die Version, die Sie verwenden würden, wenn Sie mit Kunden sprechen oder auf Ihrer Website angezeigt werden. Diese Version kann eine Zeichenfolge sein, wie ” 1.0 Release Candidate “.

Die Codeanalyse wird sich darüber beschweren (CA2243) – an Microsoft gemeldet (nicht in VS2013 behoben).

Die AssemblyInformationalVersion ist optional. Wenn nicht angegeben, wird AssemblyFileVersion verwendet.

Ich benutze das Format: major.minor [revision as string] . Dies würde zu folgenden Ergebnissen führen:

 [assembly: AssemblyInformationalVersion("1.0 RC1")] 

Versionierung von Assemblys in .NET kann eine verwirrende Perspektive sein, da derzeit mindestens drei Möglichkeiten zur Angabe einer Version für Ihre Assembly bestehen.

Hier sind die drei wichtigsten versionsbezogenen Assembly-Attribute:

 // 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")] 

Laut Vereinbarung werden die vier Teile der Version als Hauptversion , Nebenversion , Build und Revision bezeichnet .

Die AssemblyFileVersion soll einen Build der einzelnen Assembly eindeutig identifizieren

In der Regel legen Sie die Major AssemblyFileVersion und die Minor AssemblyFileVersion manuell so fest, dass sie die Version der Assembly widerspiegeln, und erhöhen dann Build und / oder Revision jedes Mal, wenn das Buildsystem die Assembly kompiliert. Die AssemblyFileVersion sollte Ihnen ermöglichen, ein Build der Assembly eindeutig zu identifizieren, sodass Sie es als Ausgangspunkt für das Debuggen von Problemen verwenden können.

In meinem aktuellen Projekt haben wir den Build-Server, der die Änderungslistennummer von unserem Quellcodeverwaltungsrepository in die Build- und Revisionsteile der AssemblyFileVersion codiert. Dies ermöglicht uns, direkt von einer Assembly auf ihren Quellcode für jede vom Build-Server generierte Assembly abzubilden (ohne die Verwendung von Labels oder Zweigen in der Quellcodeverwaltung oder die manuelle Speicherung von Datensätzen veröffentlichter Versionen).

Diese Versionsnummer wird in der Win32-Versionsressource gespeichert und kann angezeigt werden, wenn die Windows Explorer-Eigenschaftenseiten für die Assembly angezeigt werden.

Die CLR interessiert sich nicht für die AssemblyFileVersion und untersucht sie auch nicht.

Die AssemblyInformationalVersion soll die Version Ihres gesamten Produkts darstellen

Die AssemblyInformationalVersion soll eine kohärente Versionierung des gesamten Produkts ermöglichen, das aus vielen Assemblys bestehen kann, die unabhängig voneinander versioniert sind, möglicherweise unterschiedliche Versionierungsrichtlinien haben und möglicherweise von verschiedenen Teams entwickelt wurden.

“Beispielsweise könnte Version 2.0 eines Produkts mehrere Assemblys enthalten. Eine dieser Assemblys ist als Version 1.0 markiert, da es sich um eine neue Assembly handelt, die nicht in der Version 1.0 des gleichen Produkts ausgeliefert wurde. In der Regel legen Sie die Haupt- und Nebenstellen dieser Versionsnummer als öffentliche Version Ihres Produkts fest. Dann erhöhen Sie die Build- und Revisionsteile jedes Mal, wenn Sie ein komplettes Produkt mit all seinen Baugruppen verpacken. “- Jeffrey Richter, [CLR via C # (Zweite Ausgabe)] p. 57

Die CLR interessiert sich nicht für die AssemblyInformationalVersion und untersucht sie auch nicht.

Die AssemblyVersion ist die einzige Version, die der CLR wichtig ist (aber sie kümmert sich um die gesamte AssemblyVersion )

Die AssemblyVersion wird von der CLR verwendet, um an stark benannte Assemblies zu binden. Es wird in der AssemblyDef-Manifest-Metadatentabelle der erstellten Assembly und in der AssemblyRef-Tabelle jeder Assembly, die darauf verweist, gespeichert.

Dies ist sehr wichtig, da dies bedeutet, dass Sie beim Verweis auf eine stark benannte Assembly fest an eine bestimmte AssemblyVersion dieser Assembly gebunden sind. Die gesamte AssemblyVersion muss genau übereinstimmen, damit die Bindung erfolgreich ist. Wenn Sie z. B. zur Build-Zeit auf Version 1.0.0.0 einer Assembly mit starkem Namen verweisen, aber zur Laufzeit nur Version 1.0.0.1 dieser Assembly verfügbar ist, schlägt die Bindung fehl. (Sie müssen dies dann umgehen, indem Sie die Baugruppenbindungsumleitung verwenden .)

Verwirrung darüber, ob die gesamte AssemblyVersion übereinstimmen muss. (Ja tut es.)

Es gibt ein wenig Verwirrung darüber, ob die gesamte AssemblyVersion genau übereinstimmen muss, damit eine Assembly geladen werden kann. Manche Leute glauben, dass nur der Major- und der Minor-Teil der AssemblyVersion übereinstimmen müssen, damit die Bindung erfolgreich ist. Dies ist eine vernünftige Annahme, ist jedoch letztendlich falsch (ab .NET 3.5), und es ist trivial, dies für Ihre Version der CLR zu überprüfen. Führen Sie einfach diesen Beispielcode aus .

Auf meiner Maschine schlägt die zweite assembly-Ladung fehl, und die letzten beiden Zeilen des Fusionsprotokolls machen völlig klar, warum:

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

Ich denke, dass die Quelle dieser Verwirrung wahrscheinlich darin liegt, dass Microsoft ursprünglich beabsichtigt hatte, bei dieser strengen Übereinstimmung der vollständigen AssemblyVersion etwas nachsichtiger zu sein, indem nur die Major- und Minor-Versionsteile abgeglichen wurden:

“Beim Laden einer Assembly findet die CLR automatisch die neueste installierte Wartungsversion, die mit der Haupt- / Nebenversion der angeforderten Assembly übereinstimmt.” – Jeffrey Richter, [CLR via C # (Zweite Ausgabe)] p. 56

Dies war das Verhalten in Beta 1 der 1.0 CLR, jedoch wurde diese function vor der 1.0-Version entfernt und konnte in .NET 2.0 nicht wiederhergestellt werden:

“Hinweis: Ich habe gerade beschrieben, wie Sie an Versionsnummern denken sollten. Leider behandelt die CLR Versionsnummern nicht auf diese Weise. [In .NET 2.0] behandelt die CLR eine Versionsnummer als undurchsichtigen Wert. Wenn eine Assembly von Version 1.2.3.4 einer anderen Assembly abhängt, versucht die CLR nur die Version 1.2.3.4 zu laden (es sei denn, eine verbindliche Umleitung ist vorhanden) ). Microsoft plant jedoch, den Loader der CLR in einer zukünftigen Version zu ändern, sodass die neueste Version für eine bestimmte Haupt- / Nebenversion einer Assembly geladen wird . Wenn beispielsweise in einer zukünftigen Version der CLR der Loader versucht, die Version 1.2.3.4 einer Assembly zu finden, und die Version 1.2.5.0 vorhanden ist, nimmt der Loader automatisch die neueste Wartungsversion auf. Das wird eine willkommene Abwechslung beim CLR Loader sein – ich kann es kaum erwarten. “- Jeffrey Richter, [CLR via C # (Zweite Ausgabe)] p. 164 (Hervorhebung von mir)

Da diese Änderung noch nicht implementiert wurde, kann man davon ausgehen, dass Microsoft diese Absicht zurück verfolgt hat, und es ist vielleicht zu spät, dies jetzt zu ändern. Ich habe versucht, im Internet zu suchen, um herauszufinden, was mit diesen Plänen passiert ist, aber ich konnte keine Antworten finden. Ich wollte immer noch auf den Grund gehen.

Also schrieb ich Jeff Richter eine E-Mail und fragte ihn direkt – ich dachte, wenn jemand wüsste, was passiert ist, würde er es sein.

Er antwortete innerhalb von 12 Stunden, an einem Samstagmorgen nicht weniger, und stellte klar, dass der .NET 1.0 Beta 1 Loader diesen “automatischen Roll-Forward” -Mechanismus implementierte, um die neueste verfügbare Build und Revision einer Assembly abzurufen, aber dieses Verhalten war rückgängig gemacht, bevor .NET 1.0 ausgeliefert wurde. Später sollte es wiederbelebt werden, aber vor der Auslieferung der CLR 2.0 kam es nicht dazu. Dann kam Silverlight, das für das CLR-Team Priorität hatte, weshalb sich diese functionalität weiter verzögerte. In der Zwischenzeit sind die meisten Leute, die in den Tagen von CLR 1.0 Beta 1 dabei waren, inzwischen weitergezogen, so dass es unwahrscheinlich ist, dass trotz der harten Arbeit, die bereits in diese Phase gesteckt wurde, dies das Licht der Welt erblicken wird.

Das augenblickliche Verhalten scheint hier zu bleiben.

Es ist auch erwähnenswert aus meiner Diskussion mit Jeff, dass AssemblyFileVersion nur hinzugefügt wurde, nachdem der “automatische Roll-Forward” -Mechanismus entfernt wurde – denn nach 1.0 Beta 1 war jede Änderung an der AssemblyVersion eine bahnbrechende Änderung für Ihre Kunden nirgends, um deine Build-Nummer sicher zu speichern. AssemblyFileVersion ist dieser sichere Port, da er nie automatisch von der CLR überprüft wird. Vielleicht ist es auf diese Weise klarer, da es zwei getrennte Versionsnummern mit unterschiedlichen Bedeutungen gibt, anstatt zu versuchen, diese Trennung zwischen den Major / Minor (breaking) und den Build / Revisions (non-breaking) Teilen der AssemblyVersion vorzunehmen.

Die Quintessenz: Denken Sie sorgfältig darüber nach, wenn Sie Ihre AssemblyVersion ändern

Wenn Sie Baugruppen versenden, auf die andere Entwickler verweisen, müssen Sie sehr vorsichtig sein, wenn Sie die Assemblyversion dieser Assemblys ändern (und nicht ändern). Änderungen an der AssemblyVersion führen dazu, dass Anwendungsentwickler entweder erneut mit der neuen Version kompilieren müssen (um diese AssemblyRef-Einträge zu aktualisieren) oder mithilfe von Assembly-Bindungsumleitungen die Bindung manuell überschreiben.

  • Ändern Sie nicht die AssemblyVersion für eine Wartungsversion, die rückwärtskompatibel sein soll.
  • Ändern Sie die Assemblyversion für eine Version, von der Sie wissen, dass sie Änderungen aufweist.

Sehen Sie sich die Versionsattribute auf mscorlib noch einmal an:

 // 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")] 

Beachten Sie, dass es die AssemblyFileVersion ist, die alle interessanten Wartungsinformationen enthält (es ist der Revisionsteil dieser Version, der Ihnen sagt, auf welchem ​​Service Pack Sie sind), während die AssemblyVersion zu einem langweiligen alten 2.0.0.0 behoben ist. Jede Änderung an der AssemblyVersion würde jede .NET-Anwendung, die auf mscorlib.dll verweist, dazu zwingen, gegen die neue Version zu kompilieren!

AssemblyVersion bleibt ziemlich intern in .NET, während AssemblyFileVersion ist, was Windows sieht. Wenn Sie zu den Eigenschaften einer Assembly wechseln, die sich in einem Verzeichnis befindet, und zur Registerkarte “Version” wechseln, wird oben die AssemblyFileVersion angezeigt. Wenn Sie Dateien nach Version sortieren, wird dies vom Explorer verwendet.

Die AssemblyInformationalVersion wird der “Produktversion” zugeordnet und soll rein “von Menschen verwendet” sein.

AssemblyVersion ist sicherlich das wichtigste, aber AssemblyFileVersion würde ich auch nicht überspringen. Wenn Sie AssemblyInformationalVersion nicht bereitstellen, fügt der Compiler es für Sie hinzu, indem Sie das Stück “revision” Ihrer Versionsnummer entfernen und die Datei major.minor.build belassen.

AssemblyInformationalVersion und AssemblyFileVersion werden angezeigt, wenn Sie die Versionsinformationen zu einer Datei über Windows Explorer anzeigen, indem Sie die Dateieigenschaften anzeigen. Diese Attribute werden tatsächlich in eine VERSION_INFO Ressource kompiliert, die vom Compiler erstellt wird.

AssemblyInformationalVersion ist der Wert “Produktversion”. AssemblyFileVersion ist der Wert “Dateiversion”.

Die AssemblyVersion ist spezifisch für .NET-Assemblys und wird vom .NET-Assemblyloader verwendet, um zu ermitteln, welche Version einer Assembly zur Laufzeit geladen / gebunden werden soll.

Von diesen ist das AssemblyVersion Attribut das einzige, das von .NET absolut benötigt wird. Leider kann es auch die meisten Probleme verursachen, wenn es sich wahllos ändert, besonders wenn Sie Ihre Assemblies stark benennen.

Es ist erwähnenswert, einige andere Dinge:

1) Wie im Dialogfeld Eigenschaften von Windows Explorer für die generierte Assemblydatei gezeigt, gibt es zwei Stellen, die “Dateiversion” genannt werden. Die in der Kopfzeile des Dialogfelds angezeigte zeigt die AssemblyVersion, nicht die AssemblyFileVersion.

Im Abschnitt Andere Versionsinformationen gibt es ein weiteres Element namens “File Version”. Hier können Sie sehen, was als AssemblyFileVersion eingegeben wurde.

2) AssemblyFileVersion ist nur einfacher Text. Es muss nicht den Einschränkungen des Nummerierungsschemas entsprechen, die AssemblyVersion hat ( <65K, zB). Es kann 3.2 sein. . , wenn Sie möchten. Ihr Build-System muss die Tokens ausfüllen.

Außerdem unterliegt es nicht dem Platzhalterersatz AssemblyVersion. Wenn Sie in der Datei AssemblyInfo.cs nur den Wert “3.0.1. *” Haben, wird dies genau im Element Andere Versionsinformationen-> Dateiversion angezeigt.

3) Ich weiß nicht, wie sich ein Installer auf etwas anderes als numerische Dateiversionsnummern auswirkt.

Um diese Frage aktuell zu halten, sollte hervorgehoben werden, dass AssemblyInformationalVersion von NuGet verwendet wird und die Paketversion einschließlich eines Vorab-Suffixes widerspiegelt.

Zum Beispiel eine AssemblyVersion von 1.0.3. * Verpackt mit dem asp.net Core dotnet-cli

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

Erzeugt ein Paket mit der Version 1.0.3-ci-7, das Sie mit Reflektion unter Verwendung von überprüfen können:

 CustomAttributeExtensions.GetCustomAttribute(asm); 

Wenn die Assemblyversion einer Assembly geändert wird, müssen die referenzierenden Assemblys neu kompiliert werden, wenn sie einen starken Namen haben. Andernfalls wird die Assembly nicht geladen. Wenn es keinen starken Namen hat, wird es, wenn es nicht explizit zur Projektdatei hinzugefügt wird, beim Erstellen nicht in das Ausgabeverzeichnis kopiert, so dass Sie abhängige Assemblys vermissen können, besonders nach dem Löschen des Ausgabeverzeichnisses.