.NET 4.0には新しいGACがありますが、なぜですか?


300

%windir%\Microsoft.NET\assembly\新しいGACです。.NET 2.0-3.5アプリケーション用と.NET 4.0アプリケーション用の2つのGACを管理する必要があるということですか。

問題は、なぜですか?


7
質問してくれてありがとう。元の場所にgacが見つからなかったときも私は非常に混乱しています:)
Jasl

2
良い質問...どうもありがとう。
smwikipedia

1
質問に+1してください。私はNET 4.0で開発を開始しましたが、「デュアル」GACの問題に戸惑いました。
エルナン、

3
それには数回の反復が必要でしたが、MicrosoftはついにDLL Hellを.NETにもたらしました。わーい!
2015

回答:


181

はい、2つの異なるグローバルアセンブリキャッシュ(GAC)があるため、それぞれを個別に管理する必要があります。

.NET Framework 4.0では、GACにいくつかの変更が加えられました。GACは、CLRごとに1つずつ、2つに分割されました。

.NET Framework 2.0と.NET Framework 3.5の両方で使用されるCLRバージョンはCLR 2.0です。以前の2つのフレームワークリリースでは、GACを分割する必要はありませんでした。Net Framework 4.0で古いアプリケーションを壊す問題。

CLR 2.0とCLR 4.0の間の問題を回避するために、GACはランタイムごとにプライベートGACに分割されるようになりました。主な変更点は、CLR v2.0アプリケーションがGAC内のCLR v4.0アセンブリを認識できないことです。

ソース

どうして?

これは、.NET 4.0ではCLRの変更があったが、2.0から3.5では変更されなかったためと思われます。同じことが1.1から2.0のCLRでも起こりました。同じCLRからのものである限り、GACには異なるバージョンのアセンブリを格納する機能があるようです。彼らは古いアプリケーションを壊したくありません。

4.0でのGACの変更についてはMSDNの次の情報を参照してください。

たとえば、.NET 1.1と.NET 2.0の両方が同じGACを共有している場合、この共有GACからアセンブリをロードする.NET 1.1アプリケーションが.NET 2.0アセンブリを取得し、それによって.NET 1.1アプリケーションが破損する可能性があります。

.NET Framework 2.0と.NET Framework 3.5の両方で使用されるCLRバージョンはCLR 2.0です。この結果、以前の2つのフレームワークリリースでは、GACを分割する必要はありませんでした。古い(この場合は.NET 2.0)アプリケーションを破壊する問題は、CLR 4.0がリリースされた時点でNet Framework 4.0に再び現れます。したがって、CLR 2.0とCLR 4.0間の干渉の問題を回避するために、GACはランタイムごとにプライベートGACに分割されるようになりました。

CLRは将来のバージョンで更新されるため、同じことが期待できます。言語のみが変更されている場合は、同じGACを使用できます。


18
そのブログの投稿は単にOPの発見を要約したものであり、GACを分割する必要があった理由を説明していません。明らかではありませんが、元のGACは4.0アセンブリを個別に保つことができたはずです。彼らは新しい[AssemblyVersion]を持っています
Hans Passant

1
@ハンス:正確な理由ではないかもしれませんが、「CLR 2.0とCLR 4.0の間の問題を回避するために」と書かれていますが、質問には2つの質問が含まれていました。2つ目の質問は、「2つのGACを管理する必要があるということですか。1つは.NET 2.0-3.5アプリ用で、もう1つは.NET 4.0アプリ用です。」
ブライアンR.ボンディ

2
「たとえば、.NET 1.1と.NET 2.0の両方が同じGACを共有している場合、この共有GACからアセンブリをロードする.NET 1.1アプリケーションは、.NET 2.0アセンブリを取得できます。 、それにより.NET 1.1アプリケーションが破壊されました。」
Max Toro、

67

また、なぜGACが2つあるのか知りたいと思っていました。また、.NET 4.0のコメントセクションにあるMark Millerによる次の説明には、グローバルアセンブリキャッシュ(GAC)が2つあることがわかりました。

マークミラーは言った... 2010年6月28日12:13 PM

投稿ありがとうございます。「干渉問題」は意図的に曖昧でした。執筆時点では、問題はまだ調査中ですが、いくつかの壊れたシナリオがあったことは明らかでした。

たとえば、一部のアプリケーションはAssemby.LoadWithPartialNameを使用して、アセンブリの最新バージョンをロードします。最高バージョンがv4でコンパイルされている場合、v2(3.0または3.5)アプリはそれをロードできず、機能するバージョンがあったとしてもアプリがクラッシュします。当初、GACを元の場所に分割しましたが、Windowsのアップグレードシナリオで問題が発生しました。これらは両方とも、すでに出荷された関連コードなので、(バージョン分割されたGACを別の場所に移動しました。

これは、ほとんどのアプリケーションに影響を与えることはなく、メンテナンスの負担もありません。両方の場所は、ネイティブのGAC APIを使用してのみアクセスまたは変更する必要があります。これは、期待どおりにパーティションを処理します。これが発生する場所は、GetCachePathなどのGACのパスを公開するAPIを介して、またはマネージコードに読み込まれたmscorlibのパスを調べることです。

アセンブリIDの一部としてアーキテクチャを導入したときも、v2のリリース時にGACの場所を変更したことは注目に値します。これらはGAC_MSIL、GAC_32、およびGAC_64を追加しましたが、すべて%windir%\ assemblyにあります。残念ながら、それはこのリリースではオプションではありませんでした。

それが将来の読者に役立つことを願っています。


3
リンクされた記事に対するMillerのコメントは、トピックに対する内部の見方を提供します。
Nimesh Madhavan、2009

66

あまり意味がありません。元のGACは、さまざまなバージョンのアセンブリを格納する機能をすでに備えていました。そして、プログラムが誤って間違ったアセンブリを参照することを想定する理由はほとんどありません。すべての.NET 4アセンブリが[AssemblyVersion]を4.0.0.0に引き上げました。新しいインプロセスサイドバイサイド機能はこれを変更しないでください。

私の推測では、「GACで直接何かを参照しない」というルールに違反する.NETプロジェクトはすでに多すぎます。このサイトで何度か見たことがあります。

これらのプロジェクトの中断を回避する唯一の方法は、GACを移動することです。マイクロソフトでは、逆互換性が神聖です。


3
これは、これが事実である理由を説明しようとする唯一の答えです。+1
Ed S.

1
@Hans Passant:「GACの内容を直接参照しない」というルールはどういう意味ですか?
Max Toro

2
@Max:マシンに.NETアセンブリのコピーが2つあります。これらは、c:\ windows \ microsoft.netおよびc:\ program files \ referenceアセンブリの参照アセンブリです。そして、実行時に使用されるもの、GAC @ c:\ windows \ assembly。同じではありません。64ビットがその例です。マイクロソフトは、誰もがシェル拡張ハンドラーでGACのGACを参照しないように最善を尽くしました。そして、[参照の追加]ダイアログ。100%効果的ではない
Hans Passant 2010

@Hans Passant:直接参照は「c:\ WINDOWS \ assembly \ GAC_MSIL \ System \ 2.0.0.0__b77a5c561934e089 \ System.dll」のようなものです。新しいバージョンを追加すると、その参照がどのように壊れるのかわかりません。
Max Toro

2
@Hans Passant:「プログラムが誤って間違ったアセンブリを参照することを想定する理由はほとんどありません」ここで重要なのはAssembly.LoadWithPartialName、GACに2つのバージョンのアセンブリがある場合にどうなるかです。
Max Toro
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.