来自 .Net 项目的 .Net COM+:System.IO.FileNotFoundException

.Net COM+ from .Net project: System.IO.FileNotFoundException

我在 COM+ 应用程序中编写了 运行 的 .Net 组件。该组件继承自 ServicedComponent 并标记为 运行 作为服务器进程(因为我需要通过多个消费者的激活来维护静态数据)。

使用 RegAsm.exe:

完成注册
c:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe /codebase MyObject.dll

手动创建COM+应用程序,创建后添加组件。

如果我从 PHP 实例化我的组件,代码将按预期工作:实例是在组件服务控制台中列出的单独进程中创建的。

<?php
    $obj = new COM("MyObject.Sender");
    $obj->SendMessage("Hello world");
?>

但是,当我尝试从 .Net 测试可执行文件实例化组件时,我收到 "Cannot create ActiveX component" 异常:

Try
    Using gw = CreateObject("MyObject.Sender") 'Exception thrown HERE
        Dim gwsender As IMsgSender = gw
        gwsender.SendMessage("Hello world")
    End Using
Catch ex As Exception
    MsgBox(ex.ToString)
End Try

测试可执行文件是一个简单的 WinForm 应用程序。

将调试器设置为在出现所有异常时停止我能够获得以下 MDA:

The assembly named 'MyObject' was loaded from 'file:///c:/MyObject/bin/Debug/MyObject.dll' using the LoadFrom context. The use of this context can result in unexpected behavior for serialization, casting and dependency resolution. In almost all cases, it is recommended that the LoadFrom context be avoided. This can be done by installing assemblies in the Global Assembly Cache or in the ApplicationBase directory and using Assembly.Load when explicitly loading assemblies.

这是我所期望的,因为它是使用 /CodeBase 而不是使用 GAC 注册的。但是然后:

The assembly with display name 'MyObject' failed to load in the 'LoadFrom' binding context of the AppDomain with ID 1. The cause of the failure was: System.IO.FileNotFoundException: Could not load file or assembly 'MyObject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=92a84ff3d67c82b9' or one of its dependencies. The system cannot find the file specified.

MyObject 组件(如果从 PHP 调用它会完美加载)没有特殊的依赖项(仅 .Net)。从 sysinternal 的进程监视器跟踪我看不到任何失败,并且对我的 .dll 的访问是成功的(CreateFileMapping、加载图像等)。它看起来不像是文件访问问题,而是框架进行了一些运行时间检查。

测试 .net 客户端和 COM+ 组件都是从同一个编译器编译的;所有相关选项看起来都一样(平台设置为 x86,.Net Framework 4)。作为一项额外的调试措施,我将框架版本记录到组件和测试程序中的一个文件中,尽管它们是相同的 (4.0.30319.34209)。一切都在同一台机器上 运行。

Fusion 日志表明 运行time 尝试直接加载二进制文件(不调用 COM+ 实例)。

出于遗留原因,我需要这种扭曲的交互 (.Net-->COM+-->.Net),但我无法让它工作。可能发生了什么?

事实证明,使用 RegAsm.exe 进行注册并不是该操作的正确步骤。必须首先将程序集添加到 GAC,然后必须使用 regsvcs 实用程序创建 COM+ 应用程序。否则,.Net 根本不会查看 COM+ 目录:

"c:\Windows\Microsoft.NET\Framework\v4.0.30319\regsvcs.exe" MyObject.dll
"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\gacutil.exe" /i MyObject.dll

注意:实用程序的路径在您的系统中可能不同。