簡體   English   中英

如何以編程方式確定是否在GAC中安裝了.NET程序集?

[英]How to programmatically determine if .NET assembly is installed in GAC?

如果程序集在本地計算機上的GAC(全局程序集緩存)中注冊,那么以編程方式檢查的最簡單方法是什么? 是否有一些易於使用的.NET API,我可以給它一個程序集DLL或Assembly對象本身的位置,以檢查它是否存在於本地機器上的GAC中? 在我的情況下,我正在檢查的程序集已經加載到程序檢查的當前AppDomain中,所以我不確定調用Assembly.ReflectionOnlyLoad並且捕獲異常將像我在其他帖子中看到的那樣工作,加上看來有點hacky。

理想情況下,我想避免調用像gacutil.exe這樣的外部可執行文件來檢查。

這個問題與以下問題非常相似,但我的問題更准確一些,而且沒有一個接受的答案,所提供的答案似乎都不完整或最優:

最初我認為以下是最好的方法,但它不起作用,除非你指定程序集的全名,並且它有點hacky因為try / catch但它很簡單並適用於許多情況:

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

這是一種更好的方法,可以在沒有try / catch的情況下使用Fusion API 這是一堆更多的代碼,但它適用於部分程序集名稱:

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

檢查CodeBase是否為空

if (asm.CodeBase == null) {
     // IN GAC
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM