确定是不是正在使用 GAC 和 NGen 的程序集

Posted

技术标签:

【中文标题】确定是不是正在使用 GAC 和 NGen 的程序集【英文标题】:Determine if GAC'ed & NGen'ed assemblies are being used确定是否正在使用 GAC 和 NGen 的程序集 【发布时间】:2010-02-17 16:25:09 【问题描述】:

我如何确定是否正在使用本机图像,而加载程序在运行时没有验证程序集的签名,甚至使用 GAC 的程序集?

我有一个复杂的系统,我们正在用 NGen 进行试验,但目前我们正在从所有 DLL 所在的文件夹中运行 exe,因为有很多后期绑定依赖项,查看 Process Explorer,它看起来像 Native正在使用图像,但我如何确定我获得了全部好处并消除了加载程序验证步骤?

干杯, 格雷姆。

更新: 我从程序集绑定日志查看器中得到了很多这样的东西:

LOG: [Level 1]Start validating IL dependency MyCompany.Entities, Version=2.0.0.0, Culture=neutral, PublicKeyToken=7cd8595f4671c5dd.
LOG: Dependency evaluation succeeded.

最后

LOG: Validation of dependencies succeeded.
LOG: Start loading all the dependencies into load context.
LOG: Loading of dependencies succeeded.
LOG: Bind to native image succeeded.
Native image has correct version information.
Attempting to use native image C:\Windows\assembly\NativeImages_v2.0.50727_32\MyCompany.Mylibrary#\4710bb8309419d707681bd360088181f\MyCompany.MyLibrary.MyClass.ni.dll.
ZAP: Native image has been relocated.
Native image successfully used.

所以它使用的是本机映像,但仍在验证它们,即不使用 GAC 版本,即使那是我创建本机映像的地方,就像这样:

ngen install "MyCompany.Entites, Version=2.0.0.0, Culture=neutral, PublicKeyToken=7cd8595f4671c5dd, processorArchitecture=MSIL"

脚注: 这篇文章似乎暗示,如果程序集不是从 GAC 加载的,那么验证过程会抵消 NGen 的优势吗? CLR Inside Out - Improving Application Startup Performance (MSDN)

更新 - 正如 Nobugz 在下面的评论中指出的那样,自 3.5 SP1 以来未执行上述验证步骤,请参阅:MSDN Docs on NGen

【问题讨论】:

【参考方案1】:

您可以从 Fuslogvw.exe 工具中轻松查看。从 Visual Studio 命令提示符启动它。使用 Log Categories = Native Images, Settings + Log all 绑定到磁盘进行配置。运行你的程序。回到 fuslogvw,刷新。它将显示所有已加载程序集的列表。

双击一个条目以查看程序集是如何加载的。如果它来自 GAC,您会看到:

LOG:从 C:\Windows\assembly\GAC_MSIL\blahblah 加载的 IL 程序集

如果使用了 Ngen-ed 图像,您会看到:

LOG:绑定到原生镜像成功。

【讨论】:

+1 这看起来很有希望,但我认为这证明我的本机图像未被 GAC 使用,因此它们仍在通过加载进行验证,有效地抵消了 ngen 优势,请参阅我对原始 Q 的编辑。 @dog - 对我来说很清楚,程序集没有从 GAC 加载,但它确实使用了 Ngen-ed 图像。这很正常。不确定可能还有什么其他问题,如果您担心的话,完全信任会跳过强名称验证。 我添加了一个脚注,这是我试图消除的那篇文章中提到的加载程序验证。 @dog - 是的,这就是我在上一条评论中的意思。从 .NET 3.5 SP1 开始跳过验证,正是为了加快启动速度。 好的,只是为工程添加另一个扳手。我们的客户端代码针对 2.0,因为一些客户端仍在运行 win 2000!看来我得启动虚拟机了..!【参考方案2】:

您可以很容易地查看程序集是否来自 GAC:

Assembly assembly = Assembly.GetExecutingAssembly();

if (assembly.GlobalAssemblyCache)

    Console.WriteLine("I'm in the GAC!");

编辑:找到方法...

为了查看它是否是 NGEN 的,您必须直接读取程序集并查看 Precompile Header 字段是否具有符合 this page 的数据。我对达到这个值有点生疏,但应该这样做。我看不到通过反射方法解决的方法。

【讨论】:

我可以通过在 Process Explorer 中查看 DLL 的视图窗格来确定它们是否是 NGen,方法是将鼠标悬停在它给出完整路径的名称上,例如... c:\Windows\Assembly\NativeImages_v2.0.5072 _32\MyDll.ni.dll 为我的回答添加了一些线索。 看起来是我,但我不是故意这样做的老了,如果您进行编辑,我将能够撤消我的反对票,我很抱歉,【参考方案3】:

您可以使用VMMAP。在那里,所有 .dll(程序集)都有位置详细信息

详细说明如果您的程序集是从“C:\Windows\assembly\NativeImages(version)...”加载的,那么您的应用程序正在使用本机映像。

【讨论】:

以上是关于确定是不是正在使用 GAC 和 NGen 的程序集的主要内容,如果未能解决你的问题,请参考以下文章

.NET 4.0 NGEN x64 程序集上的符号解析不起作用

未加载 ngen-ed 程序集的符号

如何使用 Wix 和项目参考部署本机映像 (NGen)

FxCop 和 GAC 疯狂

.net 4 部分信任来自 GAC 的程序集

(28)部署强命名程序集到GAC