3

With the following code I'm querying the GAC to see if there is a certain assembly installed i it. The code itself works fine, but I only get the result for the x86 GAC. The assembly is installed in both GACs GAC_64 and GAC_32.

What do I have to do so that 'QueryAssemblyInfo' checks the x64 GAC?

  public bool IsInGac(string assemblyName)
  {
     ASSEMBLY_INFO assembyInfo = new ASSEMBLY_INFO();
     assembyInfo.cchBuf = 512;
     assembyInfo.currentAssemblyPath = new string('\0', assembyInfo.cchBuf);

     IAssemblyCache assemblyCache = null;

     IntPtr hr = NativeMethods.CreateAssemblyCache(out assemblyCache, 0);
     if (hr == IntPtr.Zero)
     {
        hr = assemblyCache.QueryAssemblyInfo(1, assemblyName, ref assembyInfo);
        if (hr != IntPtr.Zero)
        {
           return false;
        }

        return true;
     }

     return false;
  }

  internal static class NativeMethods
  {
     [DllImport("fusion.dll")]
     public static extern IntPtr CreateAssemblyCache(out IAssemblyCache ppAsmCache, int reserved);
  }

  [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")]
  internal interface IAssemblyCache
  {
     int Dummy1();
     [PreserveSig]
     IntPtr QueryAssemblyInfo(int flags, [MarshalAs(UnmanagedType.LPWStr)]string assemblyName, ref ASSEMBLY_INFO assemblyInfo);
     int Dummy2();
     int Dummy3();
     int Dummy4();
  }

  [StructLayout(LayoutKind.Sequential)]
  internal struct ASSEMBLY_INFO
  {
     public int cbAssemblyInfo;
     public int assemblyFlags;
     public long assemblySizeInKB;

     [MarshalAs(UnmanagedType.LPWStr)]
     public String currentAssemblyPath;

     public int cchBuf;
  }
Antineutrino
  • 1,093
  • 3
  • 10
  • 26
  • The application that you are running this code from, is it built for x86 or x64? I am curious if it queries whichever GAC corresponds to the application it is being called from... – CodingWithSpike Aug 28 '12 at 11:52
  • This is a normal .NET application which runs as a 64 bit process on x64 machines. – Antineutrino Aug 28 '12 at 11:56

2 Answers2

2
    [DllImport("fusion.dll")]
    public static extern IntPtr CreateAssemblyCache(...)

The return type for this function is HRESULT. Which is an int, not IntPtr in C#. Same thing on the QueryAssemblyInfo() declaration.

This could cause random failure when you target AnyCPU. Other than that the code is fine and it has no trouble finding assemblies in GAC_64 on my machine.

enter image description here

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • But you only get _one_ ASSEMBLY_INFO as the result. There are _two_ assemblies with the same name, one in the GAC_32 and one in the GAC_64. – Antineutrino Aug 28 '12 at 11:49
  • That's an inevitable limitation of QueryAssemblyInfo(), it can return only one result and doesn't permit filtering by architecture. Consider IAssemblyEnum instead. – Hans Passant Aug 28 '12 at 11:56
  • Ok, this makes sense. Are there some examples of how to use this from C#? – Antineutrino Aug 28 '12 at 12:18
  • Please use google to find examples. Like http://stackoverflow.com/questions/11050951/enumerate-all-installed-versions-of-an-assembly-in-gac – Hans Passant Aug 28 '12 at 12:35
0

This is all available via System.EnterpriseServices assembly since.NET 1.1

var publisher = new System.EnterpriseServices.Internal.Publish();
publisher.GacInstall(@"C:\Temp\MyDLL.dll")

Or

publisher.GacRemove(@"C:\Temp\MyDLL.dll")
Ostati
  • 4,623
  • 3
  • 44
  • 48