2013-10-18 2 views
6

어셈블리가 로컬 컴퓨터의 GAC (전역 어셈블리 캐시)에 등록되어있는 경우 프로그래밍 방식으로 확인하는 가장 쉬운 방법은 무엇입니까? .NET API를 사용하기 쉬운 곳이 있습니까? 어셈블리 DLL이나 Assembly 객체 자체에 위치를 지정하여 로컬 컴퓨터의 GAC에 있는지 확인하십시오. 내 경우에는 내가 검사하고있는 어셈블리가 이미 프로그램 검사의 현재 AppDomain에로드되어 있으므로 Assembly.ReflectionOnlyLoad을 호출하고 예외를 포착하는 것이 다른 게시물에서 제안 된 것처럼 보이고 작동하지 않을 것이라고 생각합니다. 해키..NET 어셈블리가 GAC에 설치되어 있는지 프로그래밍 방식으로 확인하는 방법

이상적으로는 gacutil.exe과 같은 외부 실행 파일을 호출하지 않는 것이 좋습니다.

+0

가능한 중복 http://stackoverflow.com/ 질문/1933947/gac-for-an-assembly) – JMK

+0

융합 API [IAssemblyCache.QueryAssemblyInfo] (http://stackoverflow.com/a/2611435/17034)를 사용하십시오. –

+0

@Hans 아마도 내가 완벽하게 관리되는 솔루션을 원했지만 Fusion API가 내가 원하는 것을 할 수 있다고 명시해야했습니다. 완벽하게 관리되는 솔루션을 위해 무엇을했는지에 대한 내 대답을보십시오. –

답변

11

이 질문은 다음 질문에 대한 매우 유사하지만, 내 좀 더 정확 플러스도는 허용 대답을했다 및 제공에 대한 답변 중 어느 것도 완전하거나 최적 같았다 :

원래 다음과 같은 것이 최선의 방법이라고 생각했지만 어셈블리의 전체 이름을 지정하지 않으면 try/catch의 해커 beacause와 비슷하지만 간단합니다 많은 경우에 작동합니다

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

이는 Fusion API를 사용하여 시도/캐치없이 작동하는 더 나은 방법입니다. 그것은 무리 많은 코드입니다하지만이 부분 조립 이름으로 작동합니다 코드베이스가 null의 경우

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"을 사용한다. 또한 "no"라고 말하기 전에 2 가지 다른 대안을 시도해보십시오. ("AMD64"and "x86") 내가 찾지 못한 유일한 일치는 "c : \ Windows \ assembly \ GAC"내의 어셈블리였습니다. – Wolf5

0

확인

if (asm.CodeBase == null) { 
    // IN GAC 
} 
([어셈블리에 대한 GAC를 확인합니다]의
관련 문제