2013-10-18 70 views
6

如果在本地机器上的GAC(全局程序集缓存)中注册了程序集,那么以编程方式检查程序化的最简单方法是什么?有没有一些易于使用.NET API,我可以给它一个位置的程序集DLL或Assembly对象本身来检查它是否存在于本地计算机上的GAC?在我的情况下,我检查的程序集已经加载到程序检查的当前AppDomain中,所以我不确定调用Assembly.ReflectionOnlyLoad并捕获异常将像我在其他帖子中看到的那样工作,再加上那似乎是种哈克。如何以编程方式确定.NET程序集是否安装在GAC中?

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

+0

可能重复http://stackoverflow.com/ questions/1933947/check-gac-for-an-assembly) – JMK

+0

使用fusion api,[IAssemblyCache.QueryAssemblyInfo](http://stackoverflow.com/a/2611435/17034)。 –

+0

@Hans我可能应该指定我想要一个完全托管的解决方案,但你是正确的,Fusion API也会做我想做的。查看我的答案,了解我最终为完全托管解决方案所做的工作。 –

回答

11

这个问题是非常类似于下面的问题,但我的是一个更确切的一点,再加上既没有一个公认的答案,并没有提供答案似乎完全或最佳:

最初我以为以下是最好的方法,但它不工作,除非你指定程序集的全名,这是一种hacky因为try/catch,但它很简单而工作在很多情况下:

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; 
    } 
} 
+3

Nb。根据我的经验,assemblyFullName必须是FULL。这包括processorArchitecture = MSIL等。所以在我的测试中,我在这个测试中使用了AssemblyName.FullName +“,processorArchitecture = MSIL”。在我说“不”之前,还要尝试其他两种选择。 (“AMD64”和“x86”) 没有它的唯一匹配是“c:\ Windows \ assembly \ GAC”中的程序集,它是一组极少数的程序集。 – Wolf5

0

检查codebase为null

if (asm.CodeBase == null) { 
    // IN GAC 
} 
的[检查GAC程序集(
相关问题