如何以编程方式确定是否在GAC中安装了.NET程序集?

如果程序集在本地计算机上的GAC(全局程序集缓存)中注册,那么以编程方式检查的最简单方法是什么? 是否有一些易于使用的.NET API,我可以给它一个程序集DLL或Assembly对象本身的位置,以检查它是否存在于本地机器上的GAC中? 在我的情况下,我正在检查的程序集已经加载到程序检查的当前AppDomain中,因此我不确定调用Assembly.ReflectionOnlyLoad并且捕获exception将像我在其他post中看到的那样工作,加上看来有点hacky。

理想情况下,我想避免调用像gacutil.exe这样的外部可执行文件来检查。

这个问题与以下问题非常相似,但我的问题更准确一些,而且没有一个接受的答案,所提供的答案似乎都不完整或最优:

  • 检查GAC以获取assembly
  • 以编程方式检查Gac中是否存在dll。如果将其显示在网格中

最初我认为以下是最好的方法,但它不起作用,除非你指定程序集的全名,并且由于try / catch而有点hacky但它​​很简单并适用于许多情况:

 public static class GacUtil { public static bool IsAssemblyInGAC(string assemblyFullName) { try { return Assembly.ReflectionOnlyLoad(assemblyFullName) .GlobalAssemblyCache; } catch { return false; } } public static bool IsAssemblyInGAC(Assembly assembly) { return assembly.GlobalAssemblyCache; } } 

这是一种更好的方法,可以在没有try / catch的情况下使用Fusion API 。 这是一堆更多的代码,但它适用于部分程序集名称:

 public static class GacUtil { [DllImport("fusion.dll")] private static extern IntPtr CreateAssemblyCache( out IAssemblyCache ppAsmCache, int reserved); [ComImport] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")] private interface IAssemblyCache { int Dummy1(); [PreserveSig()] IntPtr QueryAssemblyInfo( int flags, [MarshalAs(UnmanagedType.LPWStr)] string assemblyName, ref AssemblyInfo assemblyInfo); int Dummy2(); int Dummy3(); int Dummy4(); } [StructLayout(LayoutKind.Sequential)] private struct AssemblyInfo { public int cbAssemblyInfo; public int assemblyFlags; public long assemblySizeInKB; [MarshalAs(UnmanagedType.LPWStr)] public string currentAssemblyPath; public int cchBuf; } public static bool IsAssemblyInGAC(string assemblyName) { var assembyInfo = new AssemblyInfo { cchBuf = 512 }; assembyInfo.currentAssemblyPath = new string('\0', assembyInfo.cchBuf); IAssemblyCache assemblyCache; var hr = CreateAssemblyCache(out assemblyCache, 0); if (hr == IntPtr.Zero) { hr = assemblyCache.QueryAssemblyInfo( 1, assemblyName, ref assembyInfo); if (hr != IntPtr.Zero) { return false; } return true; } Marshal.ThrowExceptionForHR(hr.ToInt32()); return false; } } 

检查CodeBase是否为空

 if (asm.CodeBase == null) { // IN GAC }