【问题标题】:Is it possible to Load an assembly from the GAC without the FullName?是否可以在没有全名的情况下从 GAC 加载程序集?
【发布时间】:2011-09-01 13:15:15
【问题描述】:

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

【问题讨论】:

  • 这就是 Assembly.LoadWithPartialName() 的设计目的。自 2.0 以来,大 [已过时],这是理所当然的。

标签: c# assemblies load gac


【解决方案1】:

这是一段允许执行此操作的代码,以及一个示例:

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

【讨论】:

  • 哇!看起来很复杂!我一直在寻找更简单的东西,但恕我直言,您提出的解决方案肯定是实现这一目标的最佳选择!谢谢,如果有一天我的需要成为强制性的,我会试试的!
  • 很棒的工作西蒙。如代码项目中所述,我已将此答案用于 TypeResolver 类:codeproject.com/Articles/641878/…
【解决方案2】:

是的,这就是 GAC 的重点。运行时会先查看 GAC,然后再查看当前目录。

【讨论】:

  • 感谢您提供的详细信息,但我想知道是否有技巧可以做,例如 Assembly.Load("myAssembly") 而不是 Assembly.Load("myAssembly, Version=xxxxx, PublicKeyToken=xxxxxx") 恕我直言,这是不可能的,但我现在正在寻找了解大会我的 MSI 中主要输出的名称,并将其放入 app.config,以便在代码中动态获取程序集名称。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-23
  • 2021-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多