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

时间:2010-08-30 08:22:30

标签: .net com marshalling typelib tlbimp

目前的配置是:

  1. 主要应用程序未受管理。
  2. 它包含DLL,包含TLB,它描述了暴露给COM模型的函​​数。
  3. 为了支持ASMX Web服务,它加载.NET框架,并启动提供Web服务调用的ASP.NET域。
  4. 要提供Web服务调用,它需要来自主应用程序的数据。所以,我们是 从TLB生成Interop程序集(使用tlbimp.exe),Web服务程序集使用此Interop与主应用程序中的COM对象进行通信。
  5. 在我们遇到版本问题之前,一切正常。当在同一台计算机上安装了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 个答案:

答案 0 :(得分:3)

嗯,这就是解决问题的方法。

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

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

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