.NET 4.0具有新的GAC,为什么?


300

%windir%\Microsoft.NET\assembly\是新的GAC。这是否意味着现在我们必须管理两个GAC,一个用于.NET 2.0-3.5应用程序,另一个用于.NET 4.0应用程序?

问题是,为什么?


7
感谢您提出问题
。.

2
好问题...非常感谢。
smwikipedia 2010年

1
为您的问题+1。我开始在NET 4.0下进行开发,但对“双重” GAC问题感到困惑。
埃尔南

3
他们花了几次迭代,但微软终于将DLL Hell带到了.NET。好极了!
没必要,2015年

Answers:


181

是的,因为有两个不同的全局程序集缓存(GAC),所以您将不得不分别管理它们。

在.NET Framework 4.0中,GAC进行了一些更改。GAC分为两个,每个CLR一个。

用于.NET Framework 2.0和.NET Framework 3.5的CLR版本是CLR 2.0。在前两个框架​​版本中,无需拆分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发生了相同的事情。看起来,GAC能够存储不同版本的程序集,只要它们来自同一CLR。他们不想破坏旧的应用程序。

请参阅MSDN中有关4.0中GAC更改的以下信息。

例如,如果.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。因此,在前两个框架​​版本中无需拆分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 2010年

1
@汉斯:也许不是确切的原因,但它确实说:“为避免CLR 2.0和CLR 4.0之间出现问题”,这个问题里面也有2个问题。第二个问题是:“这是否意味着我们现在必须管理两个GAC,一个用于.NET 2.0-3.5应用程序,另一个用于.NET 4.0应用程序?”
Brian R. Bondy

2
您应该从一个链接中引用它:“例如,如果.NET 1.1和.NET 2.0共享相同的GAC,则从此共享的GAC加载程序集的.NET 1.1应用程序可以获取.NET 2.0程序集,从而破坏了.NET 1.1应用程序。”
Max Toro

67

我也想知道为什么2 GAC,发现如下马克·米勒解释评论部分.NET 4.0有2全局程序集缓存(GAC)

马克·米勒(Mark Miller)说... 2010年6月28日下午12:13

感谢您的帖子。“干扰问题”是故意含糊的。在撰写本文时,这些问题仍在调查中,但是很明显,有几种破碎的情况。

例如,某些应用程序使用Assemby.LoadWithPartialName加载程序集的最高版本。如果最高版本是使用v4编译的,则v2(3.0或3.5)应用无法加载,即使存在可以使用的版本,该应用也会崩溃。最初,我们在GAC的原始位置下对其进行了分区,但这在Windows升级方案中造成了一些问题。这两个都涉及已经交付的代码,因此我们将(版本分区的GAC)移到了另一个地方。

这不会对大多数应用程序产生任何影响,也不会增加任何维护负担。只能使用本机GAC API来访问或修改这两个位置,这将按预期处理分区。通过API公开GAC的路径(例如GetCachePath),或检查加载到托管代码中的mscorlib的路径,可以做到这一点。

值得注意的是,在发布v2时以及在引入架构作为程序集标识的一部分时,我们也修改了GAC位置。那些添加了GAC_MSIL,GAC_32和GAC_64,尽管它们都仍在%windir%\ assembly下。不幸的是,这不是该版本的选项。

希望它对将来的读者有所帮助。


3
Miller对链接文章的评论确实提供了对该主题的内部了解。
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 \ reference程序集中的参考程序集。运行时使用的是GAC @ c:\ windows \ assembly。它们并不相同,以64位为例。Microsoft尽力避免任何人使用Shell扩展处理程序引用GAC。和“添加引用”对话框。并非100%有效
Hans Passant 2010年

@Hans Passant:直接引用类似于“ c:\ WINDOWS \ assembly \ GAC_MSIL \ System \ 2.0.0.0__b77a5c561934e089 \ System.dll”,我看不到添加新版本如何破坏该引用。
Max Toro 2010年

2
@Hans Passant:“而且没有理由假设程序会偶然引用错误的程序集”,我想关键是Assembly.LoadWithPartialName,如果我们在GAC上有2个版本的程序集,会发生什么?
Max Toro
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.