.net - 自動 - AssemblyVersion、AssemblyFileVersion、AssemblyInformationalVersionの違いは何ですか?




ファイル と アセンブリ の バージョン が 等しい ため 勝者 を 判別 できません で した (5)

.NETでのアセンブリのバージョン管理は、アセンブリのバージョンを指定する方法が現在少なくとも3つありますが、混乱する可能性があります。

次の3つのバージョン関連のアセンブリ属性があります。

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

慣例により、バージョンの4つの部分は、 メジャーバージョンマイナーバージョンビルド 、およびリビジョンと呼ばれます。

AssemblyFileVersionは、 個々のアセンブリのビルドを一意に識別するためのものです

通常、メジャーとマイナーのAssemblyFileVersionを手動で設定してアセンブリのバージョンを反映させ、ビルドシステムがアセンブリをコンパイルするたびにビルドまたはリビジョンを増やします。 AssemblyFileVersionを使用すると、アセンブリのビルドを一意に識別できるので、問題をデバッグするための開始点として使用できます。

私の現在のプロジェクトでは、ビルドサーバーで、ソース管理リポジトリからAssemblyFileVersionのビルドとリビジョンにチェンジリスト番号をエンコードしています。 これにより、アセンブリサーバーから生成されたアセンブリ(ソース管理でラベルやブランチを使用したり、リリースされたバージョンのレコードを手動で保持しなくても)をアセンブリからそのソースコードに直接マップすることができます。

このバージョン番号は、Win32バージョンのリソースに格納されており、アセンブリのWindowsエクスプローラプロパティページを表示するときに表示されます。

CLRは、AssemblyFileVersionを気にしたり、調べたりしません。

AssemblyInformationalVersionは、製品全体のバージョンを表すためのものです

AssemblyInformationalVersionは、製品全体を一貫してバージョン管理することを目的としています。異なるバージョン管理ポリシーを使用して独立してバージョン管理され、異種のチームによって開発される可能性があります。

たとえば、製品のバージョン2.0にはいくつかのアセンブリが含まれている場合があります。 これらのアセンブリの1つは、同じ製品のバージョン1.0に含まれていない新しいアセンブリであるため、バージョン1.0としてマークされています。 通常、このバージョン番号のメジャーおよびマイナー部分を設定して、製品のパブリックバージョンを表します。 次に、完全な製品をすべてのアセンブリでパッケージ化するたびに、ビルドとリビジョンの部分をインクリメントします。」 - Jeffrey Richter、[CLR via C#(Second Edition)] p。 57

CLRは、AssemblyInformationalVersionを気にしたり、調べたりしません。

AssemblyVersionは、CLRが気にしている唯一のバージョンです(しかし、 AssemblyVersion全体について気にしています)

AssemblyVersionは、CLRによって厳密な名前のアセンブリにバインドされるために使用されます。 これは、ビルドされたアセンブリのAssemblyDefマニフェストメタデータテーブル、およびそれを参照するアセンブリのAssemblyRefテーブルに格納されます。

これは非常に重要です。なぜなら、厳密な名前のアセンブリを参照すると、そのアセンブリの特定のAssemblyVersionに緊密にバインドされているということになります。 バインディングが成功するには、AssemblyVersion全体が完全一致でなければなりません。 たとえば、ビルド時に厳密な名前のアセンブリのバージョン1.0.0.0を参照するが、そのアセンブリのバージョン1.0.0.1のみが実行時に使用可能な場合、バインディングは失敗します。 (これを回避するには、 アセンブリバインディングリダイレクトを使用する必要があります)。

AssemblyVersion全体が一致する必要があるかどうかを混乱させる。 (はい、そうです。)

アセンブリをロードするためにAssemblyVersion全体が正確に一致する必要があるかどうかは、少し混乱しています。 バインディングを成功させるためにはAssemblyVersionのメジャーとマイナー部分だけが一致しなければならないという誤った信念のもとにいる人もいます。 これは合理的な前提ですが、最終的には間違っています(.NET 3.5以降)。これをCLRのバージョンで確認するのは簡単ではありません。 このサンプルコードを実行するだけです

私のマシンでは、2番目のアセンブリのロードに失敗し、融合ログの最後の2行で完全に明確になります。

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

私はこの混乱の原因はおそらく、Microsoftが元々AssemblyVersionの厳密なマッチングについて少しだけ寛大であることを意図していたからだと思います。

「アセンブリをロードするとき、CLRは、要求されているアセンブリのメジャー/マイナーバージョンに一致する最新のインストールされたサービスバージョンを自動的に見つけます」 - Jeffrey Richter、[CLR via C#(Second Edition)] p。 56

これは1.0 CLRのBeta 1での動作でしたが、この機能は1.0リリースより前に削除されていましたが、.NET 2.0では再管理できませんでした。

"注:バージョン番号の考え方を説明したばかりです。 残念ながら、CLRはこのようにバージョン番号を扱いません。 [.NET 2.0では] CLRはバージョン番号を不透明な値として扱い、アセンブリが別のアセンブリのバージョン1.2.3.4に依存する場合、CLRはバージョン1.2.3.4のみを読み込もうとします(バインディングのリダイレクトが適切でない限り)。 ただし、 Microsoftでは、CLRのローダーを将来のバージョンで変更して、特定のメジャー/マイナーバージョンのアセンブリに対して最新のビルド/リビジョンを読み込む予定です。 たとえば、CLRの将来のバージョンでは、ローダがアセンブリのバージョン1.2.3.4を見つけようとしていて、バージョン1.2.5.0が存在する場合、ローダーは自動的に最新のサービスバージョンを取得します。 これは、CLRのローダーにとって非常に歓迎された変更です。私は待つことはできません」 - Jeffrey Richter、[CLR via C#(Second Edition)] p。 164(強調鉱山)

この変更はまだ実装されていないため、マイクロソフトがこの目的でバックトラックしていると仮定することは安全だと思いますが、今これを変更するのはおそらく遅すぎます。 私はこれらの計画で何が起こったのかをウェブで調べようとしましたが、何の答えも見つけられませんでした。 私はまだそれの底に到達したかった。

だから私はジェフ・リヒターに電子メールを送り、彼に直接尋ねた。誰かが何が起こったのか分かっていれば、それは彼だろう。

彼は土曜日の朝に12時間以内に返答し、.NET 1.0ベータ1ローダーがアセンブリの最新のビルドとリビジョンをピックアップするこの「自動ロールフォワード」メカニズムを実装したことを明らかにしましたが、この動作は.NET 1.0が出荷される前に元に戻りました。 これは後でこれを復活させることを意図していましたが、CLR 2.0が出荷される前に復活させていませんでした。 その後、CLRチームにとって優先順位を取ったSilverlightが登場したので、この機能はさらに遅れました。 その間に、CLR 1.0 Beta 1の時代にあった人々の大半は、それ以来移動してきました。したがって、すでにそれが行われていたにもかかわらず、これが日の光を見ることはほとんどありません。

現在の行動は、ここに残っているようだ。

Jeffとの私の議論から、AssemblyFileVersionは1.0のベータ1以降、AssemblyVersionの変更が顧客の急変であったため、自動ロールフォワードメカニズムが削除された後にのみ追加されたことにも注目してください。あなたのビルド番号を安全に保存する場所はありません。 AssemblyFileVersionは、CLRによって自動的に検査されることはないため、安全な避難所です。 おそらく、AssemblyVersionのメジャー/マイナー(破損)とビルド/リビジョン(非破損)の部分を分離しようとするのではなく、2つの別々のバージョン番号を別々の意味で持っている方が明らかでしょう。

結論: AssemblyVersionを変更するときは注意深く考えてください

他の開発者が参照する予定のアセンブリを出荷している場合は、アセンブリのAssemblyVersionをいつ変更するか(また変更しないか)に非常に注意する必要があります。 AssemblyVersionを変更すると、アプリケーション開発者は新しいバージョン(AssemblyRefエントリを更新する)に対して再コンパイルするか、アセンブリバインディングのリダイレクトを使用してバインディングを手動でオーバーライドする必要があります。

  • 下位互換性があるサービスリリースのAssemblyVersion 変更しないでください
  • あなたの変更が壊れていることが分かっているリリースのAssemblyVersionを変更してください

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

興味深いすべてのサービス情報(このバージョンのリビジョン部分です)を含むAssemblyFileVersionですが、AssemblyVersionは退屈な古い2.0.0.0に修正されています。 AssemblyVersionを変更すると、mscorlib.dllを参照するすべての.NETアプリケーションが強制的に新しいバージョンに対して再コンパイルされます。

3つのアセンブリバージョン属性があります。 違いは何ですか? AssemblyVersionを使用して残りの部分を無視しても問題ありませんか?

MSDNさんの言葉:

  • AssemblyVersion

    帰属するアセンブリのバージョンを指定します。

  • AssemblyFileVersion

    Win32ファイルバージョンリソースに特定のバージョン番号を使用するようにコンパイラに指示します。 Win32ファイルのバージョンは、アセンブリのバージョン番号と同じである必要はありません。

  • AssemblyInformationalVersion

    アセンブリマニフェストの追加バージョン情報を定義します。

これは、 アセンブリアトリビュートを使用するためのベストプラクティスは何ですか?


AssemblyInformationalVersionAssemblyFileVersionは、ファイルのプロパティを表示してWindowsエクスプローラを使用してファイルの「バージョン」情報を表示すると表示されます。 これらの属性は、コンパイラによって作成されたVERSION_INFOリソースに実際にコンパイルされます。

AssemblyInformationalVersionは「製品バージョン」の値です。 AssemblyFileVersionは "File version"の値です。

AssemblyVersionは.NETアセンブリに固有のもので、実行時にロード/バインドするアセンブリのバージョンを知るために.NETアセンブリローダーによって使用されます。

これらのうち、.NETで絶対に必要とされるのはAssemblyVersion属性だけです。 残念ながら、特にアセンブリの名前を強く指定している場合は、無差別に変更するときに最も問題が発生する可能性があります。


AssemblyVersion

アセンブリを参照する他のアセンブリがどこに見えるか。 この番号が変更された場合、他のアセンブリはアセンブリへの参照を更新する必要があります。 AssemblyVersionが必要です。

私はフォーマットmajor.minorを使用します。 これは次のようになります。

[assembly: AssemblyVersion("1.0")]

AssemblyFileVersion

展開に使用されます。 展開ごとにこの数を増やすことができます。 セットアッププログラムで使用されます。 AssemblyVersionが同じAssemblyVersion 、異なるビルドから生成されたアセンブリをマークする場合に使用します。

Windowsでは、ファイルのプロパティで表示できます。

可能であれば、MSBuildによって生成されるようにしてください。 AssemblyFileVersionはオプションです。 指定されていない場合、AssemblyVersionが使用されます。

私はmajor.minor.revision.buildというフォーマットを使用しています。ここでは、開発段階(Alpha、Beta、RC、RTM)のリビジョン、サービスパック、 ホットフィックスを使用しています。 これは次のようになります。

[assembly: AssemblyFileVersion("1.0.3100.1242")]

AssemblyInformationalVersion

アセンブリの製品バージョン。 これは、顧客と話をするときやウェブサイトに表示するときに使用するバージョンです。 このバージョンは ' 1.0 Release Candidate 'のような文字列にすることができます。

コード分​​析はそれについて文句を言います(CA2243) - マイクロソフトに報告されます (VS2013で修正されていません)。

AssemblyInformationalVersionはオプションです。 指定されていない場合、AssemblyFileVersionが使用されます。

私はmajor.minor [revision as string]という書式を使用します。 これは次のようになります。

[assembly: AssemblyInformationalVersion("1.0 RC1")]

この質問を最新に保つために、 AssemblyInformationalVersionがNuGetによって使用され、リリース前のサフィックスを含むパッケージのバージョンが反映されていることを強調する価値があります。

例えば、asp.net core dotnet-cliでパッケージされたAssemblyVersion 1.0.3。*

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

バージョン1.0.3-ci-7のパッケージを作成します。このパッケージは、以下を使用してリフレクションで検査することができます。

CustomAttributeExtensions.GetCustomAttribute<AssemblyInformationalVersionAttribute>(asm);

アセンブリのAssemblyVersionが変更された場合、そのアセンブリの名前が強い場合、参照するアセンブリを再コンパイルする必要があります。そうでない場合、アセンブリはロードされません。 厳密な名前がない場合、プロジェクトファイルに明示的に追加されていなければ、ビルド時には出力ディレクトリにコピーされないため、特に出力ディレクトリをクリーニングした後で、依存するアセンブリを見逃す可能性があります。





attributes