首页 文章

如何让.NET不使用已注册的TLB来编组调用COM方法?

提问于
浏览
3

目前的配置是:

  • 主应用程序是不受管理的 .

  • 它包含DLL,包含TLB,它描述了暴露给COM模型的函数 .

  • 为了支持ASMX Web服务,它加载.NET框架,并启动提供Web服务调用的ASP.NET域 .

  • 要提供Web服务调用,它需要主应用程序中的数据 . 因此,我们从TLB生成Interop程序集(使用tlbimp.exe),Web服务程序集使用此Interop与主应用程序中的COM对象进行通信 .

在我们遇到版本问题之前,一切正常 . 当在同一台计算机上安装了2个版本的应用程序(包含2个版本的TLB)时,TLB的两个版本(例如,2.0和2.1)都会被注册,而较低版本会停止工作 . ProcessMonitor显示,当试图调用版本2.0实例的Web服务时,它会查看TLB的GUID的注册表,读取所有带有版本号的子键,获取最后一个版本(2.1)并开始读取其内容 . 之后,它读取版本2.1的DLL,并且无法在自己的进程中进行COM调用 - 据我所知,由于编组问题 .

如何使Interop不需要TLB(至少存在已注册的TLB)来进行进程内COM调用?

提前致谢 .

1 回答

  • 3

    好吧,这就是问题解决的方式 .

    .NET似乎加载TLB为每个ASP.NET线程构建新的公寓(当新线程第一次尝试访问某些COM接口时,一切都会发生) . 它似乎使用CoMarshalInterThreadInterfaceInStream和CoGetInterfaceAndReleaseStream函数来实现此目的 . 我无法证明这一点,但调用这些函数会产生相同的效果:查询系统注册表并加载最高兼容版本的TLB(相同的主要版本,最高次要版本) . CoGetInterfaceAndReleaseStream行为不受manifest的影响 .

    因此,真正的问题是我们的项目不遵循Microsoft建议的版本编号规则:具有相同主要版本的COM接口应该是兼容的 .

    找到的唯一解决方案是拼接:获取LoadTypeLib函数(OleAut32.dll)的地址,并在其开头设置JMP指令 . JMP进入我们的实现,它检查正在加载的TLB的名称,如果它是已知的TLB之一 - 重定向读取到本地目录 .

相关问题