当前位置:  开发笔记 > 编程语言 > 正文

COM互操作程序集加载顺序

如何解决《COM互操作程序集加载顺序》经验,为你挑选了1个好方法。

我的Outlook插件遇到了非常奇怪的程序集引用问题和加载问题.这是细节(长篇大论:)):

我有一个旧的Outlook插件,使用.Net 1.1编写和构建.在其自己的应用程序域中使用非托管填充程序加载插件.即使用户的计算机上没有1.1,也可以使用.Net 2.0.

该插件使用由VS 2003针对Outlook 2000创建的自定义Outlook互操作程序集,并在该重建之后进行强名称(就像我的插件一样).

在addin项目中,我只引用了这个自定义互操作程序集,没有引用官方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完整类型是:Outlook.ApplicationClass,Interop.Outlook,Version = 9.0.0.0,Culture = neutral,PublicKeyToken = 4cfbdc5349cf59d8

这正是我所期望的.

问题是,当调用OnConnection(对象应用程序,Extensibility.ext_ConnectMode connectMode,对象addInInst,ref System.Array自定义)时,我在日志中看到(我有一个当前域的AssemblyLoad事件的钩子)MS interop程序集也被加载:

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

输出:

程序集Microsoft.Office.Interop.Outlook,Version = 12.0.0.0,Culture = neutral,PublicKeyToken = 71e9bce111e9429c从以下位置加载: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应用程序对象的完整类型是: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程序集?

    如何在不同的程序集中定义的不相关的类/接口之间进行转换?

注意:我创建了一个新的插件,非常简单,只是加载.我可以重现这个问题,所以真的,有人知道CLR如何决定加载和从哪里加载.除了在GAC中,还有另一个地方(注册表???)COM对象和它需要的互操作之间有链接吗?



1> Dirk Vollmar..:

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

当用户尝试添加对具有已注册PIA的类型库的引用时,Visual Studio将默默使用已注册的PIA,而不是使用Tlbimp重新导入类型库.这确保了尽可能使用PIA.

这意味着当您向项目添加对自己的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应该删除密钥并重新添加对您自己的IA的引用应该给出预期的结果.

但是,如果有可用的PIA,Microsoft建议不要使用自定义IA.我不明白这个的确切原因,但我认为这可能与编组优化和具有唯一类型定义有关.

推荐阅读
kikokikolove
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有