Programmatically To check dll exists in Gac or not.If so display it in grid
Asked Answered
c#
M

6

12

I will have a list of dll's in a folder, I want to check a dll for a application exists or not. If so i want to add that application name in grid.Can any one tell how to do it programmatically. Thanks in Advance

Mason answered 28/7, 2010 at 18:35 Comment(4)
If you have a list of DLLs in a folder, it is very unlikely that folder happens to be part of the GAC.Nyx
Very closely releated: https://mcmap.net/q/483479/-check-gac-for-an-assemblyInductee
And also: #19457047Inductee
Does this answer your question? How to programmatically determine if .NET assembly is installed in GAC?William
A
15

Do an assembly.LoadFrom and check GlobalAssemblyCache

testAssembly = Assembly.LoadFrom(dllname);

if (!testAssembly.GlobalAssemblyCache)
{
  // not in gac
}
Auberbach answered 6/7, 2012 at 19:56 Comment(1)
I see no reason for a downvote. To me, this seems like the most elegant answer so far, since it doesn't require complex stuff with Fusion/COM. This should also work if you're loading assemblies in the reflection-only contextDictograph
B
9

I think the proper way is Fusion COM API.

Here how to use it :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace IsAssemblyInGAC
{
    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 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;
    }

    class Program
    {
        static void Main()
        {
            try
            {
                Console.WriteLine(QueryAssemblyInfo("System"));
            }
            catch(System.IO.FileNotFoundException e)
            {
                Console.WriteLine(e.Message);
            }
        }

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

            IAssemblyCache assemblyCache = null;

            // Get IAssemblyCache pointer
            IntPtr 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;
        }
    }
}

Use QueryAssemblyInfo method.

Burtis answered 28/7, 2010 at 19:7 Comment(2)
HRESULT is defined as a 32 bit integer, so CreateAssemblyCache and QueryAssemblyInfo should return int rather than IntPtr.Moulin
What are the Dummy1(), Dummy2()... for?Greggrega
P
3

Here's the documentation for the undocumented GAC API: DOC: Global Assembly Cache (GAC) APIs Are Not Documented in the .NET Framework Software Development Kit (SDK) Documentation.

This API is designed to be used from native code, so this article might help you program it from C#.

If you're after a quick solution, gacutil /l works.

Psilomelane answered 28/7, 2010 at 18:41 Comment(0)
K
0

Usually people make the assumption that the GAC is located in c:<windir>\assembly, which is 99% true. So you could write code to iterate through the files found in that folder.

The more orthodox way would be to use the Fusion API, which is COM-based. A managed wrapper is available on this blog site:

Link

The site also contains sample managed code showing how to use the Fusion API to enumerate the installed assemblies - the code is pretty much written out for you, so just ctrl+c and then ctrl+v... :)

Link

HTH...

Kiwi answered 28/7, 2010 at 18:59 Comment(0)
M
0

I know this is an old question, but for sake of new travellers...

We have a (free) fusion library available for download at http://dilithium.co.za/info/products/gac-api/ which does exactly this. Disclosure: Yes, I'm affiliated. No, I won't get money if you download. ;-)

Megillah answered 10/10, 2013 at 12:26 Comment(0)
W
0

You can load dotnet exe as and find their dependecy as follows :

var applicationExeWithPath ="C:\.......\someapplicaiton.exe" 

var assemblies = Assembly.LoadFile(applicationExeWithPath ).GetReferencedAssemblies();

then iterate over those assembly and check if they exist in GAC or not

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;
    }
}
William answered 30/5, 2021 at 6:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.