3

目前的配置是:

  1. 主应用程序是非托管的。
  2. 它包含DLL,包含TLB,描述函数,暴露给COM模型。
  3. 为了支持 ASMX Web 服务,它加载 .NET 框架,并启动为 Web 服务调用提供服务的 ASP.NET 域。
  4. 为了提供 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 调用 - 据我所知,由于编组问题。

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

提前致谢。

4

1 回答 1

3

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

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

所以,真正的问题是我们的项目没有遵循微软推荐的版本编号规则:具有相同主要版本的 COM 接口应该兼容。

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

于 2010-09-06T09:49:01.630 回答