是否可以在不使用FullName的情况下从GAC加载程序集

本文关键字:情况下 GAC 程序集 加载 FullName 是否 | 更新日期: 2023-09-27 17:57:47

我知道如何从文件名和GAC加载程序集。由于我的.msi文件将把一个dll项目放入GAC,我想知道是否有可能在不知道全名的情况下从GAC加载它(我的意思是只使用程序集名称,甚至是dll文件名),因为我必须从另一个项目加载此程序集。

是否可以在不使用FullName的情况下从GAC加载程序集

下面是一段允许这样做的代码,以及一个示例:

    string path = GetAssemblyPath("System.DirectoryServices");
    Assembly.LoadFrom(path);

注意,如果你需要一个特定的处理器架构,因为它支持部分名称,你可以写这样的东西:

    // load from the 32-bit GAC
    string path = GetAssemblyPath("Microsoft.Transactions.Bridge.Dtc, ProcessorArchitecture=X86");
    // load from the 64-bit GAC
    string path = GetAssemblyPath("Microsoft.Transactions.Bridge.Dtc, ProcessorArchitecture=AMD64");

这就是实现:

    /// <summary>
    /// Gets an assembly path from the GAC given a partial name.
    /// </summary>
    /// <param name="name">An assembly partial name. May not be null.</param>
    /// <returns>
    /// The assembly path if found; otherwise null;
    /// </returns>
    public static string GetAssemblyPath(string name)
    {
        if (name == null)
            throw new ArgumentNullException("name");
        string finalName = name;
        AssemblyInfo aInfo = new AssemblyInfo();
        aInfo.cchBuf = 1024; // should be fine...
        aInfo.currentAssemblyPath = new String(''0', aInfo.cchBuf);
        IAssemblyCache ac;
        int hr = CreateAssemblyCache(out ac, 0);
        if (hr >= 0)
        {
            hr = ac.QueryAssemblyInfo(0, finalName, ref aInfo);
            if (hr < 0)
                return null;
        }
        return aInfo.currentAssemblyPath;
    }

    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")]
    private interface IAssemblyCache
    {
        void Reserved0();
        [PreserveSig]
        int QueryAssemblyInfo(int flags, [MarshalAs(UnmanagedType.LPWStr)] string assemblyName, ref AssemblyInfo assemblyInfo);
    }
    [StructLayout(LayoutKind.Sequential)]
    private struct AssemblyInfo
    {
        public int cbAssemblyInfo;
        public int assemblyFlags;
        public long assemblySizeInKB;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string currentAssemblyPath;
        public int cchBuf; // size of path buf.
    }
    [DllImport("fusion.dll")]
    private static extern int CreateAssemblyCache(out IAssemblyCache ppAsmCache, int reserved);

是的,这就是GAC的全部要点。运行时将首先在GAC中查找,然后再查找当前目录。