如何以编程方式确定 GAC 中是否安装了 .NET 程序集? [英] How to programmatically determine if .NET assembly is installed in GAC?

查看:32
本文介绍了如何以编程方式确定 GAC 中是否安装了 .NET 程序集?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以编程方式检查程序集是否已在本地计算机上的 GAC(全局程序集缓存)中注册的最简单方法是什么?是否有一些易于使用的 .NET API,我可以在其中为程序集 DLL 或程序集对象本身提供一个位置,以检查它是否存在于本地计算机上的 GAC 中?在我的情况下,我正在检查的程序集已经加载到程序检查的当前 AppDomain 中,所以我不确定调用 Assembly.ReflectionOnlyLoad 并捕获异常是否会像我看到的建议一样工作在其他帖子中,再加上这似乎有点笨拙.

What's the easiest way to check programmatically if an assembly is registered in the GAC (Global Assembly Cache) on the local machine? Is there some easy to use .NET API where I can give it a location to an assembly DLL or an Assembly object itself to check if it exists in GAC on the local machine? In my case the assembly I'm checking will already be loaded in the current AppDomain of the program checking so I'm not sure calling Assembly.ReflectionOnlyLoad and catching an exception will work like I've seen suggested in other posts, plus that seems kind of hacky.

理想情况下,我想避免调用像 gacutil.exe 这样的外部可执行文件来检查.

Ideally I'd like to avoid calling an external executable like gacutil.exe to check.

推荐答案

这个问题与以下问题非常相似,但我的问题更精确一点,而且都没有被接受的答案,而且提供的答案似乎都不是完整的或最佳的:

This question is very similar to the following questions but mine is a little more precise, plus neither had an accepted answer and none of the answers offered seemed complete or optimal:

最初我认为以下是最好的方法,但除非您指定程序集的全名,否则它不起作用,并且由于 try/catch 有点麻烦,但它很简单并且适用于许多情况:

Originally I thought the following was the best approach but it doesn't work unless you specify the full name of the assembly and it's kind of hacky beacause of the try/catch but it's simple and works for many cases:

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.这是一堆更多的代码,但它适用于部分程序集名称:

This is a better approach that works without a try/catch by using the Fusion API. It's a bunch more code but it works with partial assembly names:

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('', 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;
    }
}

这篇关于如何以编程方式确定 GAC 中是否安装了 .NET 程序集?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆