.NET 4.0 ma nowy GAC, dlaczego?

300

%windir%\Microsoft.NET\assembly\jest nowym GAC . Czy to oznacza, że ​​teraz musimy zarządzać dwoma GAC, jednym dla aplikacji .NET 2.0-3.5, a drugim dla aplikacji .NET 4.0?

Pytanie brzmi: dlaczego?

Max Toro
źródło
7
dzięki za pytanie… jestem również bardzo zdezorientowany, gdy nie znalazłem gac w jego oryginalnej lokalizacji :)
Jasl
2
Dobre pytanie ... Wielkie dzięki.
smwikipedia,
1
+1 za twoje pytanie. Zacząłem programować pod NET 4.0 i byłem zdezorientowany „podwójnym” problemem GAC.
Hernán
3
Zajęło im to kilka iteracji, ale Microsoft ostatecznie przyniósł DLL Hell do .NET. Tak!
nic nie jest potrzebne

Odpowiedzi:

181

Tak, ponieważ istnieją 2 odrębne pamięci podręczne Global Assembly Cache (GAC), będziesz musiał zarządzać każdym z nich osobno.

W .NET Framework 4.0 GAC przeszedł kilka zmian. GAC został podzielony na dwa, po jednym dla każdego CLR.

Wersja CLR używana zarówno w .NET Framework 2.0, jak i .NET Framework 3.5 to CLR 2.0. W poprzednich dwóch wydaniach ramowych nie było potrzeby dzielenia GAC. Problem zerwania starszych aplikacji w Net Framework 4.0.

Aby uniknąć problemów między CLR 2.0 i CLR 4.0, GAC jest teraz podzielony na prywatne GAC dla każdego środowiska wykonawczego. Główna zmiana polega na tym, że aplikacje CLR v2.0 nie mogą teraz widzieć zespołów CLR v4.0 w GAC.

Źródło

Dlaczego?

Wygląda na to, że nastąpiła zmiana CLR w .NET 4.0, ale nie w wersji 2.0 na 3.5. To samo stało się z CLR od 1.1 do 2.0. Wydaje się, że GAC ma możliwość przechowywania różnych wersji zestawów, o ile pochodzą one z tego samego CLR. Nie chcą zrywać starych aplikacji.

Zobacz następujące informacje w MSDN na temat zmian GAC w 4.0 .

Na przykład, jeśli zarówno .NET 1.1, jak i .NET 2.0 współdzieliły ten sam GAC, wówczas aplikacja .NET 1.1, ładująca zestaw z tego wspólnego GAC, mogłaby uzyskać zestawy .NET 2.0, powodując w ten sposób uszkodzenie aplikacji .NET 1.1

Wersja CLR używana zarówno w .NET Framework 2.0, jak i .NET Framework 3.5 to CLR 2.0. W wyniku tego w poprzednich dwóch wydaniach ramowych nie było potrzeby dzielenia GAC. Problem przerywania starszych (w tym przypadku .NET 2.0) powraca w Net Framework 4.0, w którym to momencie wydano CLR 4.0. Dlatego, aby uniknąć problemów z zakłóceniami między CLR 2.0 i CLR 4.0, GAC jest teraz podzielony na prywatne GAC dla każdego środowiska wykonawczego.

Ponieważ CLR jest aktualizowany w przyszłych wersjach, możesz oczekiwać tego samego. Jeśli zmieni się tylko język, możesz użyć tego samego GAC.

Brian R. Bondy
źródło
18
Ten post na blogu jedynie przypomina odkrycie PO, ale nie wyjaśnia, dlaczego GAC musiał zostać podzielony. Nie jest oczywiste, że oryginalny GAC byłby w stanie rozdzielić zespoły 4.0 od siebie. Mają nową [AssemblyVersion]
Hans Passant
1
@Hans: Może nie jest to dokładny powód, ale mówi: „Aby uniknąć problemów między CLR 2.0 a CLR 4.0”, pytanie zawierało w sobie również 2 pytania. Drugie pytanie brzmi: „czy to oznacza, że ​​teraz musimy zarządzać dwoma GAC, jednym dla aplikacji .NET 2.0-3.5, a drugim dla aplikacji .NET 4.0?”
Brian R. Bondy
2
Powinieneś zacytować to w jednym z linków: „Na przykład, jeśli zarówno .NET 1.1, jak i .NET 2.0 współdzieliły ten sam GAC, wówczas aplikacja .NET 1.1, ładująca zestaw z tego wspólnego GAC, mogłaby uzyskać zestawy .NET 2.0 , co powoduje uszkodzenie aplikacji .NET 1.1. ”
Max Toro,
67

Chciałem wiedzieć, dlaczego 2 GAC i stwierdzono następujące wyjaśnienie przez Marka Millera w komentarzach z .NET 4.0 posiada 2 Global Assembly Cache (GAC) :

Mark Miller powiedział ... 28 czerwca 2010 12:13

Dzięki za post. „Problemy z zakłóceniami” były celowo niejasne. W momencie pisania tego tekstu problemy były nadal badane, ale było jasne, że było kilka zepsutych scenariuszy.

Na przykład niektóre aplikacje używają Assemby.LoadWithPartialName, aby załadować najwyższą wersję zestawu. Jeśli najwyższa wersja została skompilowana z wersją v4, aplikacja v2 (3.0 lub 3.5) nie mogłaby jej załadować, a aplikacja ulegałaby awarii, nawet gdyby istniała wersja, która działałaby. Pierwotnie podzieliliśmy GAC na partycje w jego oryginalnej lokalizacji, ale spowodowało to pewne problemy ze scenariuszami aktualizacji systemu Windows. Oba dotyczyły kodu, który już został wysłany, więc przenieśliśmy nasz (GAC z partycjonowaniem wersji w inne miejsce).

Nie powinno to mieć żadnego wpływu na większość aplikacji i nie powoduje żadnych obciążeń związanych z konserwacją. Obie lokalizacje powinny być dostępne lub modyfikowane tylko przy użyciu rodzimych interfejsów API GAC, które zajmują się partycjonowaniem zgodnie z oczekiwaniami. Miejsca, w których to się pojawia, znajdują się za pośrednictwem interfejsów API, które ujawniają ścieżki GAC, takich jak GetCachePath, lub badanie ścieżki mscorlib załadowanej do kodu zarządzanego.

Warto zauważyć, że zmodyfikowaliśmy lokalizacje GAC, kiedy wydaliśmy v2, a także kiedy wprowadziliśmy architekturę jako część tożsamości zestawu. Te dodały GAC_MSIL, GAC_32 i GAC_64, chociaż wszystkie nadal znajdują się poniżej zestawu% windir% \. Niestety nie było takiej opcji w tym wydaniu.

Mam nadzieję, że pomoże to przyszłym czytelnikom.

Jasl
źródło
3
Komentarze Millera do powiązanego artykułu zapewniają poufne spojrzenie na ten temat.
Nimesh Madhavan
66

To nie ma większego sensu, oryginalny GAC był już w stanie przechowywać różne wersje zespołów. I nie ma powodu, by zakładać, że program kiedykolwiek przypadkowo odniesie się do niewłaściwego zestawu, wszystkie zestawy .NET 4 mają podwyższoną wartość [AssemblyVersion] do 4.0.0.0. Nowa równoległa funkcja nie powinna tego zmieniać.

Domyślam się, że było już zbyt wiele projektów .NET, które złamały zasadę „nigdy nie odwołuj się do niczego bezpośrednio w GAC”. Widziałem to już kilka razy na tej stronie.

Tylko jeden sposób, aby uniknąć zerwania z tymi projektami: przesunąć GAC. Kompatybilność wsteczna jest święta w Microsoft.

Hans Passant
źródło
3
To jedyna odpowiedź, która próbuje wyjaśnić, dlaczego tak jest. +1
Ed S.
1
@Hans Passant: Co rozumiesz przez „nigdy nie odwołuj się bezpośrednio do zasady GAC”?
Max Toro,
2
@Max: na twoim komputerze są dwie kopie zestawów .NET. Te mają być zestawami referencyjnymi w zestawach c: \ windows \ microsoft.net i c: \ program files \ odwołania. A te używane w czasie wykonywania, GAC @ c: \ windows \ assembly. Nie są takie same, przykładem może być 64-bit. Microsoft starał się, aby nikt nie odwoływał się do GAC za pomocą programu obsługi rozszerzenia powłoki. I okno dialogowe Dodaj odniesienie. Nie w 100% skuteczne
Hans Passant
@Hans Passant: Bezpośrednie odniesienie to coś w rodzaju „c: \ WINDOWS \ assembly \ GAC_MSIL \ System \ 2.0.0.0__b77a5c561934e089 \ System.dll”, nie widzę, jak dodanie nowej wersji złamałoby to odniesienie.
Max Toro,
2
@Hans Passant: „I nie ma powodu, aby przypuszczać, że program kiedykolwiek przypadkowo odwoła się do niewłaściwego zestawu”. Myślę, że kluczem jest to Assembly.LoadWithPartialName, co się stanie, jeśli będziemy mieć 2 wersje zestawu w GAC?
Max Toro,