.NET 4.0 มี GAC ใหม่ทำไม


300

%windir%\Microsoft.NET\assembly\คือใหม่GAC ตอนนี้เราต้องจัดการ GAC สองตัวแล้วหนึ่งตัวสำหรับ. NET 2.0-3.5 และอีกหนึ่งสำหรับ. NET 4.0

คำถามคือทำไม


7
ขอบคุณสำหรับการขอ question..i ยังกำลังสับสนมากเมื่อฉันไม่พบ gac ในตำแหน่งเดิม :)
Jasl

2
เป็นคำถามที่ดี ... ขอบคุณมาก
smwikipedia

1
+1 สำหรับคำถามของคุณ ฉันเริ่มพัฒนาภายใต้ NET 4.0 และสับสนกับปัญหา "คู่" GAC,
Hernán

3
ใช้เวลาทำซ้ำสองสามครั้ง แต่สุดท้าย Microsoft ก็นำ DLL Hell มาที่. NET เย้!
nothingisnecessary

คำตอบ:


181

ใช่เนื่องจากมี Global Assembly Cache (GAC) 2 ตัวที่แตกต่างกันคุณจะต้องจัดการแต่ละรายการแยกกัน

ใน. NET Framework 4.0 GAC ผ่านการเปลี่ยนแปลงเล็กน้อย GAC ถูกแบ่งออกเป็นสองส่วนหนึ่งสำหรับแต่ละ CLR

รุ่น CLR ที่ใช้สำหรับทั้ง. NET Framework 2.0 และ. NET Framework 3.5 คือ CLR 2.0 ไม่จำเป็นในการเผยแพร่สองเฟรมเวิร์กก่อนหน้านี้เพื่อแยก GAC ปัญหาการแตกแอปพลิเคชันรุ่นเก่าใน Net Framework 4.0

เพื่อหลีกเลี่ยงปัญหาระหว่าง CLR 2.0 และ CLR 4.0 ตอนนี้ GAC จะถูกแบ่งเป็น GAC ส่วนตัวสำหรับแต่ละรันไทม์การเปลี่ยนแปลงหลักคือแอปพลิเคชัน CLR v2.0 ในขณะนี้ไม่สามารถเห็นแอสเซมบลี CLR v4.0 ใน GAC

แหล่ง

ทำไม?

ดูเหมือนว่าจะเป็นเพราะมีการเปลี่ยนแปลง CLR ใน. NET 4.0 แต่ไม่ใช่ใน 2.0 เป็น 3.5 สิ่งเดียวกันนี้เกิดขึ้นกับ 1.1 ถึง 2.0 CLR ดูเหมือนว่า GAC มีความสามารถในการจัดเก็บแอสเซมบลีเวอร์ชันต่าง ๆ ตราบเท่าที่พวกเขามาจาก CLR เดียวกัน พวกเขาไม่ต้องการทำลายแอปพลิเคชันเก่า

ดูข้อมูลต่อไปนี้ในMSDN เกี่ยวกับการเปลี่ยนแปลงใน GAC 4.0

ตัวอย่างเช่นหากทั้ง. NET 1.1 และ. NET 2.0 ได้แชร์ GAC เดียวกันดังนั้นแอปพลิเคชัน. NET 1.1 ที่โหลดแอสเซมบลีจาก GAC ที่แชร์นี้สามารถรับแอสเซมบลี. NET 2.0 ได้ดังนั้นจึงทำให้แอปพลิเคชัน. NET 1.1

รุ่น CLR ที่ใช้สำหรับทั้ง. NET Framework 2.0 และ. NET Framework 3.5 คือ CLR 2.0 ด้วยเหตุนี้จึงไม่มีความจำเป็นในสองเฟรมเวิร์กก่อนหน้านี้ที่จะแยก GAC ปัญหาของการแบ่งแอปพลิเคชันที่เก่ากว่า (ในกรณีนี้คือ. NET 2.0) จะกลับมาทำงานอีกครั้งใน Net Framework 4.0 ณ จุดที่ CLR 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 คำถามอยู่ข้างใน คำถามที่สองคือ: "มันหมายความว่าตอนนี้เราต้องจัดการ GAC สองตัวหนึ่งอันสำหรับ. NET 2.0-3.5.5 และอีกหนึ่งสำหรับ. NET 4.0 apps?"
Brian R. Bondy

2
คุณควรอ้างอิงสิ่งนี้จากลิงก์ใดลิงก์หนึ่งของคุณ: "ตัวอย่างเช่นถ้าทั้ง. NET 1.1 และ. NET 2.0 ใช้ GAC เดียวกันร่วมกันแล้วแอปพลิเคชั่น......... 1.1 1.1 โหลดแอสเซมบลีจาก GAC ที่ใช้ร่วมกันนี้ ดังนั้นจึงทำลายแอปพลิเคชัน. NET 1.1 "
Max Toro

67

ฉันต้องการทราบว่าทำไม 2 GAC และพบคำอธิบายต่อไปนี้โดย Mark Millerในส่วนความคิดเห็นของ. NET 4.0 มี 2 Global Assembly Cache (GAC) :

มาร์คมิลเลอร์กล่าวว่า ... 28 มิถุนายน 2010 12:13 PM

ขอบคุณสำหรับการโพสต์ "ปัญหาการแทรกแซง" นั้นคลุมเครือ ในช่วงเวลาของการเขียนปัญหายังอยู่ระหว่างการตรวจสอบ แต่เห็นได้ชัดว่ามีหลายสถานการณ์ที่แตกหัก

ตัวอย่างเช่นบางแอปพลิเคชันใช้ Assemby.LoadWithPartialName เพื่อโหลดแอสเซมบลีเวอร์ชันสูงสุด หากเวอร์ชันสูงสุดถูกคอมไพล์ด้วย v4 แสดงว่าแอป v2 (3.0 หรือ 3.5) ไม่สามารถโหลดได้และแอปจะหยุดทำงานแม้ว่าจะมีเวอร์ชันที่ใช้งานได้ เริ่มแรกเราแบ่งพาร์ติชัน GAC ภายใต้ที่ตั้งดั้งเดิม แต่นั่นทำให้เกิดปัญหาบางอย่างกับสถานการณ์การอัพเกรด windows รหัสที่เกี่ยวข้องทั้งคู่ที่ส่งมาแล้วดังนั้นเราจึงย้าย (GAC รุ่นที่แบ่งพาร์ติชันไปยังที่อื่น

สิ่งนี้จะไม่ส่งผลกระทบใด ๆ ต่อแอพพลิเคชั่นส่วนใหญ่และไม่เพิ่มภาระการบำรุงรักษาใด ๆ ทั้งสองตำแหน่งควรเข้าถึงหรือแก้ไขโดยใช้ GAC API ดั้งเดิมซึ่งจัดการกับการแบ่งพาร์ติชันตามที่คาดไว้ สถานที่ที่พื้นผิวทำผ่าน APIs ที่แสดงเส้นทางของ GAC เช่น GetCachePath หรือตรวจสอบเส้นทางของ mscorlib ที่โหลดเข้าไปในรหัสที่ได้รับการจัดการ

เป็นที่น่าสังเกตว่าเราได้แก้ไขตำแหน่ง GAC เมื่อเราเปิดตัว v2 เช่นกันเมื่อเราแนะนำสถาปัตยกรรมเป็นส่วนหนึ่งของข้อมูลประจำตัวของการชุมนุม ที่เพิ่ม GAC_MSIL, GAC_32 และ GAC_64 แม้ว่าทั้งหมดจะยังอยู่ภายใต้% windir% \ assembly น่าเสียดายที่นั่นไม่ใช่ตัวเลือกสำหรับรุ่นนี้

หวังว่ามันจะช่วยให้ผู้อ่านในอนาคต


3
ความคิดเห็นของมิลเลอร์ในบทความที่เชื่อมโยงจะทำให้มุมมองบุคคลภายในของหัวข้อ
Nimesh Madhavan

66

ไม่สมเหตุสมผลนัก GAC ดั้งเดิมนั้นมีความสามารถในการจัดเก็บชุดประกอบรุ่นต่างๆ และมีเหตุผลเล็กน้อยที่จะสันนิษฐานว่าโปรแกรมจะตั้งใจอ้างอิงแอสเซมบลีที่ไม่ถูกต้องโดยไม่ตั้งใจแอสเซมบลี. NET 4 ทั้งหมดได้รับ [AssemblyVersion] กระแทกสูงสุด 4.0.0.0 คุณลักษณะที่อยู่ระหว่างดำเนินการใหม่ไม่ควรเปลี่ยนแปลงสิ่งนี้

ฉันเดา: มีโครงการ. NET จำนวนมากเกินไปอยู่ที่นั่นซึ่งทำลายกฎ "ไม่เคยอ้างอิงอะไรเลยใน GAC โดยตรง" ฉันเคยเห็นมันทำในเว็บไซต์นี้หลายครั้ง

ทางเดียวเท่านั้นที่จะหลีกเลี่ยงการทำลายโครงการเหล่านั้น: ย้าย GAC กลับกันเป็นสิ่งศักดิ์สิทธิ์ที่ Microsoft


3
นี่เป็นคำตอบเดียวที่พยายามอธิบายว่าทำไมในกรณีนี้ +1
Ed S.

1
@Hans Passant: คุณหมายถึงอะไรโดยกฎ "ไม่อ้างอิงอะไรเลยใน GAC โดยตรง"
Max Toro

2
@ Max: มีแอสเซมบลี. NET อยู่สองชุดในเครื่องของคุณ สิ่งเหล่านั้นหมายถึงแอสเซมบลีอ้างอิงใน c: \ windows \ microsoft.net และ c: \ program แอสเซมบลีอ้างอิง \ files \ และสิ่งที่ใช้ในรันไทม์คือ GAC @ c: \ windows \ assembly พวกเขาจะไม่เหมือนกัน 64- บิตจะเป็นตัวอย่าง Microsoft พยายามอย่างเต็มที่ที่จะหลีกเลี่ยงใครก็ตามที่อ้างถึง GAC ด้วยตัวจัดการส่วนขยายของเชลล์ และกล่องโต้ตอบเพิ่มการอ้างอิง ไม่มีประสิทธิภาพ 100%
Hans Passant

@Hans Passant: การอ้างอิงโดยตรงคือ 'c: \ WINDOWS \ assembly \ GAC_MSIL \ System \ 2.0.0.0__b77a5c561934e089 \ System.dll' ฉันไม่เห็นว่าการเพิ่มเวอร์ชันใหม่จะทำให้การอ้างอิงนั้นผิด
Max Toro

2
@Hans Passant: "และมีเหตุผลเล็กน้อยที่จะสมมติว่าโปรแกรมจะอ้างถึงชุดประกอบที่ไม่ถูกต้องโดยไม่ตั้งใจ" ฉันคิดว่ากุญแจที่นี่คือจะAssembly.LoadWithPartialNameเกิดอะไรขึ้นถ้าเรามีชุดประกอบ 2 รุ่นใน GAC?
Max Toro
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.