Was sind die Unterschiede zwischen AssemblyVersion, AssemblyFileVersion und AssemblyInformationalVersion?

860

Es gibt drei Assemblyversionsattribute. Was sind Unterschiede? Ist es in Ordnung, wenn ich AssemblyVersionden Rest benutze und 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.

  • AssemblyInformationalVersion :

    Definiert zusätzliche Versionsinformationen für ein Assemblymanifest.


Dies ist eine Fortsetzung von Was sind die Best Practices für die Verwendung von Baugruppenattributen?

Jakub Šturc
quelle

Antworten:

907

AssemblyVersion

Wo andere Baugruppen suchen, die auf Ihre Baugruppe verweisen. Wenn sich diese Anzahl ändert, müssen andere Baugruppen ihre Verweise auf Ihre Baugruppe aktualisieren! Aktualisieren Sie diese Version nur, wenn die Abwärtskompatibilität beeinträchtigt ist. Das AssemblyVersionist erforderlich.

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

[assembly: AssemblyVersion("1.0")]

Wenn Sie SemVer strikt befolgen, bedeutet dies, dass Sie nur dann aktualisieren, wenn sich die wichtigsten Änderungen ergeben, also 1.0, 2.0, 3.0 usw.

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 diese Option, um Assemblys zu markieren, die dieselbe haben AssemblyVersion, aber aus verschiedenen Builds generiert wurden.

In Windows kann es in den Dateieigenschaften angezeigt werden.

Die AssemblyFileVersion ist optional. Wenn nicht angegeben, wird die AssemblyVersion verwendet.

Ich verwende das Format: major.minor.patch.build , wobei ich SemVer für die ersten drei Teile folge und die Build-Nummer des Buildservers für den letzten Teil verwende (0 für den lokalen Build). Dies würde führen zu:

[assembly: AssemblyFileVersion("1.3.2.254")]

Beachten Sie, dass System.Version diese Teile wie folgt benennt major.minor.build.revision!

AssemblyInformationalVersion

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, z. B. ' 1.0 Release Candidate '.

Das AssemblyInformationalVersionist optional. Wenn nicht angegeben, wird die AssemblyFileVersion verwendet.

Ich benutze das Format: major.minor [.patch] [Revision als String] . Dies würde führen zu:

[assembly: AssemblyInformationalVersion("1.0 RC1")]
Rémy van Duijkeren
quelle
4
Für AssemblyFileVersion "Wenn möglich, lassen Sie es von MSBuild generieren" - Warum? Sie haben gerade einen guten Grund erklärt, es manuell zu steuern :)
mo.
3
Die Warnung im AssemblyInformationalVersion-Format ist heute (21. Mai 2013) in VS2010 noch vorhanden, und Ihr Link ist nicht mehr vorhanden.
Reinierpost
22
Leider definiert die Versionsklassemajor.minor[.build[.revision]] und nicht major.minor.revision.buildso in der angegebenen Antwort würden die Build- und Revisionsnummern ausgetauscht, wenn Sie die Klasseneigenschaften verwenden oder System.Reflection.Assembly.GetExecutingAssembly().GetName().Versiondie Build- und Revisionsnummern erkennen würden.
thinkOfaNumber
9
@thinkOfaNumber Ihr Recht bezüglich der Versionsklasse, aber das ist die Art der Microsoft-Versionierung. Ich persönlich finde es seltsam, die Build-Nummer am Ende nicht zu haben, und deshalb habe ich mein Format nur als Beispiel angegeben, basierend auf der semantischen Versionierung . Sie können den Microsoft-Weg oder natürlich Ihren eigenen Weg nutzen.
Rémy van Duijkeren
6
Zu beachten ist, dass für AssemblyInformationalVersion, wenn weggelassen, AssemblyFileVersionverwendet wird. Dann, AssemblyVersion wenn beide weggelassen werden.
Drazen Bjelovuk
588

Die Versionierung von Assemblys in .NET kann verwirrend sein, da es derzeit mindestens drei Möglichkeiten gibt, eine Version für Ihre Assembly anzugeben.

Hier sind die drei wichtigsten versionierungsbezogenen 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")]

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

Das AssemblyFileVersionsoll einen Aufbau der einzelnen Baugruppe eindeutig identifizieren

In der Regel legen Sie die Haupt- und Neben-AssemblyFileVersion manuell so fest, dass sie die Version der Assembly widerspiegelt, und erhöhen dann die Erstellung und / oder Revision jedes Mal, wenn Ihr Build-System die Assembly kompiliert. Mit der AssemblyFileVersion sollten Sie einen Build der Assembly eindeutig identifizieren können, damit Sie ihn als Ausgangspunkt für das Debuggen von Problemen verwenden können.

In meinem aktuellen Projekt hat der Build-Server die Änderungslistennummer aus unserem Versionsverwaltungs-Repository in die Build- und Revisionsteile der AssemblyFileVersion codiert. Auf diese Weise können wir für jede vom Buildserver generierte Assembly eine direkte Zuordnung von einer Assembly zu ihrem Quellcode vornehmen (ohne Beschriftungen oder Verzweigungen in der Quellcodeverwaltung verwenden oder Aufzeichnungen über freigegebene Versionen manuell führen zu müssen).

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

Die CLR kümmert sich nicht um die AssemblyFileVersion und untersucht sie auch nicht.

Das AssemblyInformationalVersionsoll die Version Ihres gesamten Produkts darstellen

Die AssemblyInformationalVersion soll eine kohärente Versionierung des gesamten Produkts ermöglichen, die aus vielen Assemblys bestehen kann, die unabhängig voneinander versioniert sind, möglicherweise mit unterschiedlichen Versionsrichtlinien, und möglicherweise von unterschiedlichen Teams entwickelt werden.

„Zum Beispiel kann Version 2.0 eines Produkts mehrere Baugruppen enthalten. Eine dieser Baugruppen ist als Version 1.0 gekennzeichnet, da es sich um eine neue Baugruppe handelt, die nicht in Version 1.0 desselben Produkts geliefert wurde. In der Regel legen Sie die Haupt- und Nebenteile dieser Versionsnummer so fest, dass sie die öffentliche Version Ihres Produkts darstellen. Dann erhöhen Sie die Build- und Revisionsteile jedes Mal, wenn Sie ein komplettes Produkt mit all seinen Baugruppen verpacken. “ - Jeffrey Richter, [CLR über C # (Zweite Ausgabe)] p. 57

Die CLR kümmert sich nicht um die AssemblyInformationalVersion und untersucht sie auch nicht.

Dies AssemblyVersionist die einzige Version, die die CLR interessiert (aber sie kümmert sich um die gesamte Version AssemblyVersion).

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

Dies ist sehr wichtig, da Sie beim Verweisen auf eine stark benannte Assembly eng an eine bestimmte AssemblyVersion dieser Assembly gebunden sind. Die gesamte AssemblyVersion muss genau übereinstimmen, damit die Bindung erfolgreich ist. Wenn Sie beispielsweise zur Erstellungszeit auf Version 1.0.0.0 einer Assembly mit starkem Namen verweisen, zur Laufzeit jedoch nur Version 1.0.0.1 dieser Assembly verfügbar ist, schlägt die Bindung fehl! (Sie müssen dies dann mithilfe der Assembly Binding Redirection umgehen .)

Verwirrung darüber, ob das Ganze 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. Einige Menschen glauben fälschlicherweise, dass nur die Haupt- und Nebenteile der AssemblyVersion übereinstimmen müssen, damit die Bindung erfolgreich ist. Dies ist eine vernünftige Annahme, die jedoch letztendlich falsch ist (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 Baugruppenlast fehl, und die letzten beiden Zeilen des Fusionsprotokolls machen deutlich, 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, die Ursache für diese Verwirrung liegt wahrscheinlich darin, dass Microsoft ursprünglich beabsichtigte, diese strikte Übereinstimmung der vollständigen AssemblyVersion etwas milder zu gestalten, indem nur die Teile der Haupt- und Nebenversion abgeglichen wurden:

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

Dies war das Verhalten in Beta 1 der 1.0 CLR. Diese Funktion wurde jedoch vor der 1.0-Version entfernt und konnte in .NET 2.0 nicht wieder auftauchen:

„Hinweis: Ich habe gerade beschrieben, wie Sie sich Versionsnummern vorstellen sollten. Leider behandelt die CLR Versionsnummern nicht so. [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 Version 1.2.3.4 zu laden (es sei denn, eine Bindungsumleitung ist vorhanden ). Allerdings hat Microsoft Pläne den CLR des Laders in einer zukünftigen Version zu ändern , so dass es die neueste Version / Revision für eine bestimmte Major / Minor Version einer Assembly lädt. Wenn der Lader beispielsweise in einer zukünftigen Version der CLR versucht, Version 1.2.3.4 einer Baugruppe zu finden, und Version 1.2.5.0 vorhanden ist, holt der Lader automatisch die neueste Wartungsversion ab. Dies wird eine sehr willkommene Änderung des Laders der CLR sein - ich kann es kaum erwarten. “ - Jeffrey Richter, [CLR über C # (Zweite Ausgabe)] p. 164 (Schwerpunkt Mine)

Da diese Änderung noch nicht implementiert wurde, kann man davon ausgehen, dass Microsoft diese Absicht zurückverfolgt hat, und es ist möglicherweise 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äre er es.

Er antwortete innerhalb von 12 Stunden, nicht weniger an einem Samstagmorgen, und stellte klar, dass der .NET 1.0 Beta 1-Lader diesen "automatischen Roll-Forward" -Mechanismus zum Abrufen des neuesten verfügbaren Builds und der neuesten Revision einer Baugruppe implementiert hat, aber dieses Verhalten war vor dem Versand von .NET 1.0 zurückgesetzt. Es war später beabsichtigt, dies wiederzubeleben, aber es hat es nicht geschafft, bevor die CLR 2.0 ausgeliefert wurde. Dann kam Silverlight, das für das CLR-Team Priorität hatte, sodass sich diese Funktionalität weiter verzögerte. In der Zwischenzeit sind die meisten Leute, die in den Tagen von CLR 1.0 Beta 1 da waren, inzwischen weitergezogen, so dass es unwahrscheinlich ist, dass dies trotz all der harten Arbeit, die bereits in sie gesteckt wurde, das Licht der Welt erblicken wird.

Das derzeitige Verhalten scheint hier zu bleiben.

Aus meiner Diskussion mit Jeff geht auch hervor, dass AssemblyFileVersion erst nach dem Entfernen des automatischen Roll-Forward-Mechanismus hinzugefügt wurde. Nach 1.0 Beta 1 war jede Änderung an AssemblyVersion eine bahnbrechende Änderung für Ihre Kunden Nirgendwo können Sie Ihre Build-Nummer sicher speichern. AssemblyFileVersion ist dieser sichere Hafen, da er von der CLR nie automatisch überprüft wird. Vielleicht ist es auf diese Weise klarer, zwei separate Versionsnummern mit unterschiedlichen Bedeutungen zu haben, als zu versuchen, diese Trennung zwischen den Teilen Major / Minor (Breaking) und Build / Revision (Non-Breaking) der AssemblyVersion vorzunehmen.

Fazit: Überlegen Sie genau, wann Sie Ihre ändern AssemblyVersion

Die Moral lautet: Wenn Sie Assemblys versenden, auf die andere Entwickler verweisen, müssen Sie äußerst vorsichtig sein, wenn Sie die AssemblyVersion dieser Assemblys ändern (und nicht ändern). Alle Änderungen an der AssemblyVersion bedeuten, dass Anwendungsentwickler entweder eine Neukompilierung mit der neuen Version durchführen müssen (um diese AssemblyRef-Einträge zu aktualisieren) oder Assemblybindungsumleitungen verwenden müssen, um die Bindung manuell zu überschreiben.

  • Sie nicht die Assemblyversion für eine Wartung Release ändern, die abwärtskompatibel gedacht.
  • Sie die Assembly ändern für eine Veröffentlichung , dass Sie wissen Bruch Änderungen hat.

Schauen Sie sich noch einmal die Versionsattribute auf mscorlib 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 sich befinden), während die AssemblyVersion auf eine langweilige alte Version 2.0.0.0 festgelegt ist. Jede Änderung an der AssemblyVersion würde jede .NET-Anwendung, die auf mscorlib.dll verweist, dazu zwingen, erneut gegen die neue Version zu kompilieren!

Daniel Fortunov
quelle
9
Gute Antwort. Ich denke, der wichtigste Punkt, den Sie angesprochen haben - und den MS ausdrücklich empfehlen sollte - ist, Änderungen an der AssemblyVersion genau dann vorzunehmen, wenn die neue Version die Abwärtskompatibilität beeinträchtigt.
mwolfe02
1
Eine der Fragen, die ich mir immer wieder stelle, ist, wann ich jede dieser Versionsnummern ändern sollte. Ihre Aufzählungspunkte in AssemblyVersion haben dies klargestellt, und die gesamte Antwort war eine interessante Lektüre.
RyanfaeScotland
Ich sehe viele Antworten, die die Konzepte hinter diesen drei Dingen erklären. Aber in welcher Beziehung stehen sie zu den bearbeitbaren Versionsnummern in den Projekteigenschaften? Wenn Sie auf Baugruppeninformationen klicken, können Sie zwei Versionen ändern. Durch Ändern der Baugruppenversion wird der Ordner geändert, in dem sich user.config befindet, und durch Ändern der Dateiversion wird die angezeigte Versionsnummer geändert, wenn Sie mit der rechten Maustaste auf die exe-Datei klicken und zu deren Eigenschaften wechseln. Wie entsprechen diese beiden Versionsnummern AssemblyVersion, AssemblyFileVersion und AssemblyInformationalVersion?
Kyle Delaney
Der Link zu dem Blog-Beitrag, den Sie ursprünglich geschrieben haben, gibt einen 404. Gibt es dafür einen neuen Ort?
Rob K
@RobK: Ah, entschuldige. Diese Website ist nicht verfügbar, aber der gesamte Inhalt des Blogposts wird in der Antwort wiedergegeben, sodass Sie nichts verpassen. Ich werde den defekten Link jetzt entfernen.
Daniel Fortunov
43

AssemblyVersionbleibt so ziemlich intern in .NET, während AssemblyFileVersionWindows dies sieht. Wenn Sie zu den Eigenschaften einer Assembly gehen, die sich in einem Verzeichnis befindet, und zur Registerkarte "Version" wechseln, AssemblyFileVersionsehen Sie diese oben. Wenn Sie Dateien nach Version sortieren, wird dies vom Explorer verwendet.

Die AssemblyInformationalVersionKarten sind der "Produktversion" zugeordnet und sollen rein "vom Menschen verwendet" werden.

AssemblyVersionist sicherlich das Wichtigste, aber ich würde es auch nicht überspringen AssemblyFileVersion. Wenn Sie nichts angeben AssemblyInformationalVersion, fügt der Compiler es für Sie hinzu, indem er das "Revisions" -Element Ihrer Versionsnummer entfernt und die Datei major.minor.build verlässt.

Bob King
quelle
23

AssemblyInformationalVersionund AssemblyFileVersionwerden angezeigt, wenn Sie die "Versions" -Informationen einer Datei über den Windows Explorer anzeigen, indem Sie die Dateieigenschaften anzeigen. Diese Attribute werden tatsächlich in eine VERSION_INFORessource kompiliert , die vom Compiler erstellt wird.

AssemblyInformationalVersionist der Wert "Produktversion". AssemblyFileVersionist der Wert "Dateiversion".

Das AssemblyVersionist spezifisch für .NET-Assemblys und wird vom .NET Assembly Loader verwendet, um zu ermitteln, welche Version einer Assembly zur Laufzeit geladen / gebunden werden soll.

Von diesen ist das AssemblyVersionAttribut das einzige, das von .NET unbedingt benötigt wird. Leider kann es auch die meisten Probleme verursachen, wenn es sich wahllos ändert, insbesondere wenn Sie Ihre Assemblys stark benennen.

Scott Dorman
quelle
9

Um diese Frage auf dem AssemblyInformationalVersionneuesten Stand zu halten, sollte hervorgehoben werden, dass sie von NuGet verwendet wird und die Paketversion einschließlich aller Suffixe vor der Veröffentlichung widerspiegelt .

Zum Beispiel eine AssemblyVersion von 1.0.3. *, Die mit dem asp.net-Kern dotnet-cli gepackt ist

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

Produziert ein Paket mit Version 1.0.3-ci-7, das Sie mit Reflexion überprüfen können, indem Sie:

CustomAttributeExtensions.GetCustomAttribute<AssemblyInformationalVersionAttribute>(asm);
KCD
quelle
7

Es lohnt sich, einige andere Dinge zu beachten:

1) Wie im Dialogfeld "Windows Explorer-Eigenschaften" für die generierte Baugruppendatei gezeigt, gibt es zwei Stellen, die als "Dateiversion" bezeichnet werden. Die in der Kopfzeile des Dialogfelds angezeigte zeigt die AssemblyVersion, nicht die AssemblyFileVersion.

Im Abschnitt Informationen zu anderen Versionen gibt es ein weiteres Element namens "Dateiversion". 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 ausführt (z. B. <build> <65K). Es kann 3.2. <Release Tag Text>. <Datetime> sein, wenn Sie möchten. Ihr Build-System muss die Token ausfüllen.

Darüber hinaus unterliegt AssemblyVersion nicht dem Platzhalterersatz. Wenn Sie in AssemblyInfo.cs nur den Wert "3.0.1. *" Haben, wird genau dies im Element Andere Versionsinformationen-> Dateiversionselement angezeigt.

3) Ich weiß jedoch nicht, wie sich die Verwendung von Versionsnummern für numerische Dateien auf ein Installationsprogramm auswirkt.

DavidM
quelle
2

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 und nicht explizit zur Projektdatei hinzugefügt wird, wird es beim Erstellen nicht in das Ausgabeverzeichnis kopiert, sodass Sie möglicherweise abhängige Assemblys verpassen, insbesondere nach dem Bereinigen des Ausgabeverzeichnisses.

linquize
quelle
Das ist sehr interessant! Könnten Sie den Teil "Wird nicht in das Ausgabeverzeichnis kopiert" näher erläutern? Vielleicht ein Link, wo dieses Verhalten definiert ist. Ich habe nie verstanden, warum einige indirekte Abhängigkeiten manchmal kopiert wurden, aber nicht immer. Dies muss zu 100% damit zusammenhängen.
Julealgon