GAC 管理器实用程序和 API
使用这个方便的工具管理全局程序集缓存 - 或者使用提供的 API 自己构建!
介绍
由于我最近的一些工作,我花了很多时间检查和搜索 GAC 中的某些程序集。我在网上找到的一些允许搜索 GAC 的工具对我来说有点慢而且很基础,所以为了方便我的开发,我编写了一个基本的 API 来检查 GAC,以及一个同样有助于此任务的基本应用程序。
在这篇文章中,我将展示 GAC 管理工具的工作原理、API 的用法以及该项目的未来规划。
GAC 管理项目
由于我希望获得对该项目的反馈并随着时间的推移对其进行改进,因此我为该项目创建了一个 CodePlex 页面,您可以在其中获取最新的源代码和二进制文件,以及提交功能请求和错误。该项目托管在
https://gacmanager.codeplex.com/
GAC 管理工具
您可以从文章顶部或 CodePlex 网站上的链接下载并安装 GAC 管理工具。安装该工具后,它会在开始菜单中创建一个快捷方式,位于名为“GAC Manager”的文件夹中。运行该工具,您将看到如下界面
我尽量保持界面尽可能简洁。工具栏允许您执行以下命令
刷新
正如您所料,此命令将刷新 GAC 中安装的程序集列表。
安装程序集
此命令允许您将程序集安装到 GAC。请注意,程序集必须是强命名!
帮助
此命令将直接带您到 CodePlex 网站,您可以在那里找到有关该应用程序的更多信息或提交错误或功能请求。
程序集详细信息
此命令显示当前选定程序集的程序集详细信息窗口
复制显示名称
此命令将选定程序集的显示名称复制到剪贴板。显示名称是程序集的限定名称(包括版本、公钥等),可用于加载反射详细信息等。
文件属性
文件属性命令会简单地调用选定程序集的 shell“文件属性”窗口。
卸载程序集
从 GAC 卸载选定的程序集。
打开包含的文件夹
该命令打开程序集所在的文件夹。
搜索
搜索框允许您通过搜索来过滤程序集的显示。显示的程序集将是名称或公钥标记中包含搜索字符串的任何程序集。
GAC 管理 API
枚举程序集、安装、卸载等所需的所有功能均由 GAC 管理 API 类库提供。该库目前使用 Fusion API 来发现 GAC 中程序集的详细信息。
枚举程序集
我们可以使用 AssemblyCacheEnumerator 对象来枚举全局程序集缓存中的程序集。示例如下
// Create an assembly enumerator.
var assemblyEnumerator = new AssemblyCacheEnumerator();
// Get the first assembly.
var assemblyName = assemblyEnumerator.GetNextAssembly();
// Start to loop through the assemblies.
while(assemblyName != null)
{
// The 'assemblyName' object is a COM interface, if we create an
// AssemblyDescription from it, we will have access to more information.
var assemblyDescription = new AssemblyDescription(assemblyName);
// Show the display name.
System.Diagnostics.Trace.WriteLine("Display Name: " + assemblyDescription.DisplayName);
// Move to the next assembly.
assemblyName = assemblyEnumerator.GetNextAssembly();
}
与许多低级 API 函数一样,IAssemblyName 对象是实际传递的对象。这是一个 COM 接口,本身并不太有用。但是,如果我们从该接口构造一个“AssemblyDescription”对象,那么我们就可以访问更多信息。AssemblyDescription 对象的外观如下
AssemblyDescription 可以从 IAssemblyName 创建,甚至可以从普通字符串创建,只要该字符串包含有效的程序集显示名称。
安装程序集
AssemblyCache 类可用于安装程序集。
// We'll need a path to the assembly to install.
var path = @"c:/MyAssembly.dll";
// Install the assembly, without an install reference.
AssemblyCache.InstallAssembly(path, null, AssemblyCommitFlags.Default);
很简单!第二个参数是 Install Reference。这是一个高级主题,超出了本文的范围,但它基本上允许您将一个程序集与另一个程序集或已安装的产品关联起来。这意味着如果有人以后尝试卸载该程序集,除非同时卸载关联的产品,否则将无法成功卸载。
卸载程序集
AssemblyCache 类可用于卸载程序集。
// We'll need a display name of the assembly to uninstall.
var displayName = @"Apex, Version=1.4.0.0, Culture=neutral, PublicKeyToken=98d06957926c086d, processorArchitecture=MSIL";
// When we try to uninstall an assembly, an uninstall disposition will be
// set to indicate the success of the operation.
var uninstallDisposition = IASSEMBLYCACHE_UNINSTALL_DISPOSITION.Unknown;
// Install the assembly, without an install reference.
try
{
AssemblyCache.UninstallAssembly(displayName, null, out uninstallDisposition);
}
catch (Exception exception)
{
// We've failed to uninstall the assembly.
throw new InvalidOperationException("Failed to uninstall the assembly.", exception);
}
// Did we succeed?
if (uninstallDisposition == IASSEMBLYCACHE_UNINSTALL_DISPOSITION.IASSEMBLYCACHE_UNINSTALL_DISPOSITION_UNINSTALLED)
{
// Hooray!
}
卸载程序集更为复杂。可能会出错的事情更多,实际上 Uninstall Disposition 枚举在让我们了解可能发生的任何情况方面非常有帮助。UninstallAssembly 函数的第二个参数是 Install Reference - 如上一节所述,这是一个更复杂的主题,但它本质上允许我们指定程序集是一个更大组件集合的一部分。
获取高级 Fusion 属性
AssemblyDescription 对象有一个名为“FusionProperties”的属性。此类包含更多高级属性,这些属性只能通过 Fusion API 获取。它们之所以存储在自己的对象中,是因为它们是惰性加载的——Fusion Properties 仅在需要时才会被发现,以确保大量程序集的初始加载速度很快。以下是如何使用它们:
// Get the first assembly in the global assembly cache.
var someAssembly = new AssemblyDescription(new AssemblyCacheEnumerator().GetNextAssembly());
// Show the install references.
foreach(var installReference in someAssembly.FusionProperties.InstallReferences)
System.Diagnostics.Trace.WriteLine(installReference.Description);
在这里,您可以看到我们可以通过 Fusion Properties 访问安装引用等高级详细信息。
获取高级反射属性
AssemblyDescription 对象还有一个名为 ReflecitonProperties 的对象,其中包含更多属性。同样,它是惰性加载的——而且原因很充分,通过反射获取程序集的属性可能会非常慢——因此,通过将这些属性分开,我们可以清楚地在代码中表明我们正在使用一个可能具有很高开销的属性。以下是如何获取它们
// Get the first assembly in the global assembly cache.
var someAssembly = new AssemblyDescription(new AssemblyCacheEnumerator().GetNextAssembly());
// Show the Runtime Version.
System.Diagnostics.Trace.WriteLine(someAssembly.ReflectionProperties.RuntimeVersio
就是这样!
未来
目前,该工具可以满足我的需求,但我很乐意对其进行改进,使其成为社区中有用的工具。如果您有任何建议,请在本篇文章或项目主页上发表评论!