gpt4 book ai didi

.net - COM 互操作程序集加载顺序

转载 作者:行者123 更新时间:2023-12-04 15:05:50 25 4
gpt4 key购买 nike

我在使用 Outlook 插件时遇到了非常奇怪的程序集引用问题和加载问题。以下是详细信息(说来话长:)):

我有一个旧的 Outlook 插件,使用 .Net 1.1 编写和构建。插件是使用其自己的应用程序域中的非托管 shim 加载的。使用 .Net 2.0 可以正常工作,即使用户机器上不存在 1.1。

该插件使用由 VS 2003 针对 Outlook 2000 创建的自定义 Outlook 互操作程序集,然后重建为强命名(就像我的插件一样)。

在插件项目中,我只引用了这个自定义互操作程序集,没有引用官方的 MS 互操作程序集。

当这个插件在 Outlook 2007 和 .Net 2.0 的环境中使用时,官方的 MS 互操作程序集安装在 GAC 中,出于某种原因,我看到插件加载并使用它们。

在 Connect 类的代码中,我有一个 using 指令:

using Outlook;

这是我的自定义互操作程序集的命名空间。

在 Connect ctor 我有这些代码行(添加用于测试目的):
Assembly.LoadFrom(PATHTOMYASSEMBLY + "Interop.Outlook.dll");
Type type = typeof(Outlook.ApplicationClass);
logger.Debug("Outlook.Application full type is: {0}", type.AssemblyQualifiedName);

这输出:

Outlook.Application full type is: Outlook.ApplicationClass, Interop.Outlook, Version=9.0.0.0, Culture=neutral, PublicKeyToken=4cfbdc5349cf59d8



这正是我所期望的。

问题是,当
OnConnection(对象应用程序,Extensibility.ext_ConnectMode 连接模式,对象 addInInst,引用 System.Array 自定义)
被调用,我在日志中看到(我有一个当前域的 AssemblyLoad 事件的 Hook ),MS 互操作程序集也被加载:
private void app_domain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
{
Assembly loadedAssembly = args.LoadedAssembly;
logger.Debug("Assembly {0} is loaded from: {1}", loadedAssembly.FullName, loadedAssembly.GlobalAssemblyCache ? "GAC" : loadedAssembly.Location);
}

输出:

Assembly Microsoft.Office.Interop.Outlook, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c is loaded from: GAC



我的 OnConnection 方法是这样开始的:
public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom)
{
Type type = application.GetType();
logger.Debug("OnConnection application object's full type is: {0}", type.AssemblyQualifiedName);

Outlook.Application applicationObject = (Outlook.Application)application;

这输出:

OnConnection application object's full type is: Microsoft.Office.Interop.Outlook.ApplicationClass, Microsoft.Office.Interop.Outlook, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c



这真的很奇怪,你可以在下一行看到我可以成功地转换到 Outlook.Application 没有任何问题。

我已经检查过 Reflector,我的程序集不以任何方式引用 Microsoft 的互操作程序集。我的 Interop.Outlook.dll 也是如此。

那么,有人知道发生了什么吗?这些问题的答案是什么:
  • 为什么它会加载 Microsoft 程序集?
  • 如何在不同程序集中定义的不相关类/接口(interface)之间进行转换?

  • 注意:我创建了一个新插件,非常简单,它什么都不做,只是加载。我可以重现这个问题,所以真的,有谁知道 CLR 如何决定加载什么互操作以及从哪里加载。除了在 GAC 中,还有其他地方(注册表???)在 COM 对象和它所需的互操作之间存在链接?

    最佳答案

    我想我在 Microsoft 的 Primary Interop Assemblies 中找到了您问题的答案。底漆。 PIA 在 Visual Studio 中的处理方式不同:

    When a user attempts to add a reference to a type library that has a registered PIA, Visual Studio will silently use the registered PIA instead of reimporting the type library with Tlbimp. This ensures that the PIA is used whenever possible.



    这意味着当你在项目中添加对你自己的 IA 的引用时,Visual Studio 会检查是否有为此 COM 对象注册的 PIA。 Outlook PIA 在以下键下注册:
    HKEY_CLASSES_ROOT\CLSID\{0006F023-0000-0000-C000-000000000046}\InprocServer32\12.0.0.0
    Assembly="Microsoft.Office.Interop.Outlook, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71E9BCE111E9429C"

    据我了解,使用 regasm 工具取消注册 PIA 应该删除 key 并重新添加对您自己的 IA 的引用应该会产生预期的结果。

    但是,如果有可用的 PIA,Microsoft 不建议使用自定义 IA。我不明白这个的确切原因,但我认为这可能与编码(marshal)优化和具有独特的类型定义有关。

    关于.net - COM 互操作程序集加载顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/338083/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com