2013-10-18 93 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程序集(
相關問題