在最近的一些开发工作中,经常需要检查和搜索全局程序集缓存(GAC)中的特定程序集。发现网络上的一些工具在搜索GAC时速度较慢且功能基础,因此编写了一个基本的API和一个应用程序来简化这一过程。
在本文中,将展示GAC管理器工具的工作原理,如何使用API,以及这个项目的未来发展。
为了收集反馈并随着时间改进这个项目,在CodePlex上为该项目创建了一个页面。可以在这里获取最新的源代码和二进制文件,提交功能请求和bug。项目托管在以下地址:
请访问该网站以获取更多信息,并提出功能请求!
GAC管理器工具可以从文章顶部的链接或CodePlex网站下载并安装。安装后,它会在开始菜单中创建一个名为'GAC Manager'的文件夹快捷方式。运行工具后,会看到一个类似这样的界面:
尽量保持界面简洁。工具栏允许执行以下命令:
GAC管理器API类库提供了枚举程序集、安装、卸载等所有必需的功能。这个库目前使用Fusion API来发现GAC中的程序集详细信息。
枚举程序集:
可以使用AssemblyCacheEnumerator对象来枚举全局程序集缓存中的程序集。示例如下:
C#
//
创建一个程序集枚举器。
var assemblyEnumerator = new AssemblyCacheEnumerator();
//
获取第一个程序集。
var assemblyName = assemblyEnumerator.GetNextAssembly();
//
开始循环遍历程序集。
while (assemblyName != null)
{
//
'assemblyName'对象是一个COM接口,如果从中创建一个
//
AssemblyDescription,将能够访问更多信息。
var assemblyDescription = new AssemblyDescription(assemblyName);
//
显示显示名称。
System.Diagnostics.Trace.WriteLine("Display Name: " + assemblyDescription.DisplayName);
//
移动到下一个程序集。
assemblyName = assemblyEnumerator.GetNextAssembly();
}
与许多底层API函数一样,IAssemblyName对象是实际传递的对象。它本身不是很有用。然而,如果从接口构建一个'AssemblyDescription'对象,那么就可以访问更多信息。AssemblyDescription对象如下所示:
AssemblyDescription可以从IAssemblyName创建,甚至可以从一个简单的字符串创建,只要该字符串包含一个有效的程序集显示名称。
AssemblyCache类可以用来安装程序集。
C#
//
需要一个要安装的程序集的路径。
var path = @"c:/MyAssembly.dll";
//
安装程序集,没有安装引用。
AssemblyCache.InstallAssembly(path, null, AssemblyCommitFlags.Default);
简单!第二个参数是安装引用。这是一个高级主题,超出了本文的范围,但它基本上允许将一个程序集与另一个程序集或已安装的产品关联起来。这意味着如果有人稍后尝试卸载该程序集,除非同时卸载相关产品,否则它将无法工作。
AssemblyCache类可以用来卸载程序集。
C#
//
需要要卸载的程序集的显示名称。
var displayName = @"Apex, Version=1.4.0.0, Culture=neutral, PublicKeyToken=98d06957926c086d, processorArchitecture=MSIL";
//
当尝试卸载程序集时,将设置一个卸载处置来指示操作的成功。
var uninstallDisposition = IASSEMBLYCACHE_UNINSTALL_DISPOSITION.Unknown;
//
安装程序集,没有安装引用。
try
{
AssemblyCache.UninstallAssembly(displayName, null, out uninstallDisposition);
}
catch (Exception exception)
{
//
未能卸载程序集。
throw new InvalidOperationException("Failed to uninstall the assembly.", exception);
}
//
成功了吗?
if (uninstallDisposition == IASSEMBLYCACHE_UNINSTALL_DISPOSITION.IASSEMBLYCACHE_UNINSTALL_DISPOSITION_UNINSTALLED)
{
//
太好了!
}
卸载程序集更复杂。有更多的事情可能会出错,实际上Uninstall Disposition枚举在让了解可能发生的事情时非常有帮助。UninstallAssembly函数的第二个参数是安装引用 - 如前一节所述,这是一个更复杂的主题,但本质上它允许指定程序集是更大组件集合的一部分。
AssemblyDescription对象有一个名为'FusionProperties'的属性。这个类包含只能通过Fusion API获取的更高级的属性。它们被存储在自己的对象中的原因是因为它们是按需加载的 - Fusion属性只有在需要时才会被发现,以确保最初加载大量程序集的速度。以下是它们的使用方法:
C#
//
获取全局程序集缓存中的第一个程序集。
var someAssembly = new AssemblyDescription(new AssemblyCacheEnumerator().GetNextAssembly());
//
显示安装引用。
foreach (var installReference in someAssembly.FusionProperties.InstallReferences)
System.Diagnostics.Trace.WriteLine(installReference.Description);
在这里,可以看到可以通过Fusion属性访问安装引用等高级详细信息。
还有一个可用的对象,它为AssemblyDescription提供了更多属性,这就是ReflectionProperties对象。同样,这是按需加载的 - 通过反射获取程序集的属性可能会非常慢 - 因此通过将这些属性分开,在代码中非常清楚地表明正在使用一个可能具有较大开销的属性。以下是如何获取它们的方法:
C#
//
获取全局程序集缓存中的第一个程序集。
var someAssembly = new AssemblyDescription(new AssemblyCacheEnumerator().GetNextAssembly());
//
显示运行时版本。
System.Diagnostics.Trace.WriteLine(someAssembly.ReflectionProperties.RuntimeVersion);