Welcome to the navigation

Dolor incididunt ullamco eu nulla dolor esse aliquip ut consequat, reprehenderit ad velit ut minim nisi voluptate quis commodo sunt excepteur in elit, laborum, magna. Labore deserunt do irure veniam, fugiat pariatur, quis velit duis in occaecat dolor voluptate in ad tempor non aliquip ut adipisicing eu in proident, nisi

Yeah, this will be replaced... But please enjoy the search!

Programmatically check if an assembly is loaded in GAC with C#

Categories Tags

Maybe you are writing an installer of some kind or are depending on some external assemblies to have your .net program or website to work, I often do. So with no further ado. Here is a small program which will lead you to success in these matters *fanfare*. Example, running in console

  

Source Code

using System;
using System.Runtime.InteropServices;

namespace ConsoleTestAssembly
{
    class Program
    {
        static void Main()
        {
            string response;

            var exist = AssemblyExist("Camelot.SharePointConnector", out response);
            Console.WriteLine(string.Concat(exist, Environment.NewLine, response, Environment.NewLine));

            exist = AssemblyExist("Camelot.SharePointIntegration", out response);
            Console.WriteLine(string.Concat(exist, Environment.NewLine, response, Environment.NewLine));

            exist = AssemblyExist("Camelot.NoExisting", out response);
            Console.WriteLine(string.Concat(exist, Environment.NewLine, response, Environment.NewLine));

            Console.ReadKey();
        }

        public static bool AssemblyExist(string assemblyname, out string response)
        {
            try
            {
                response = QueryAssemblyInfo(assemblyname);
                return true;
            }
            catch (System.IO.FileNotFoundException e)
            {
                response = e.Message;
                return false;
            }
        }

        // If assemblyName is not fully qualified, a random matching may be 
        public static String QueryAssemblyInfo(string assemblyName)
        {
            var assembyInfo = new AssemblyInfo {cchBuf = 512};
            assembyInfo.currentAssemblyPath = new String('', assembyInfo.cchBuf);

            IAssemblyCache assemblyCache;

            // Get IAssemblyCache pointer
            var hr = GacApi.CreateAssemblyCache(out assemblyCache, 0);
            if (hr == IntPtr.Zero)
            {
                hr = assemblyCache.QueryAssemblyInfo(1, assemblyName, ref assembyInfo);
                if (hr != IntPtr.Zero)
                {
                    Marshal.ThrowExceptionForHR(hr.ToInt32());
                }
            }
            else
            {
                Marshal.ThrowExceptionForHR(hr.ToInt32());
            }
            return assembyInfo.currentAssemblyPath;
        }
    }

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

    // GAC Interfaces - IAssemblyCache. As a sample, non used vtable entries 
    [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 AssemblyInfo assemblyInfo);

        int Dummy2();
        int Dummy3();
        int Dummy4();
    }

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

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

        public int cchBuf;
    }

}

Thats it.