.Net 项目中的 .Net COM+:System.IO.FileNotFoundException [英] .Net COM+ from .Net project: System.IO.FileNotFoundException

查看:69
本文介绍了.Net 项目中的 .Net COM+:System.IO.FileNotFoundException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've written a .Net component that runs in a COM+ application. The component inherits from ServicedComponent and is marked to run as a server process (because I need to maintain static data through activations from multiple consumers).

使用 RegAsm.exe 完成注册:

Registration is done using RegAsm.exe:

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

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

The COM+ application was created manually and the component added after creation.

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

If I instantiate my component from PHP the code works as expected: the instance is created in a separate process which is listed in the Component Services Console.

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

但是,当我尝试从 .Net 测试可执行文件实例化组件时,出现无法创建 ActiveX 组件"异常:

However, when I try to instantiate the component from a .Net test executable, I get a "Cannot create ActiveX component" exception:

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 应用程序.

The test executable is a simple WinForm application.

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

Setting the debugger to stop at all exceptions I was able to get the following MDAs:

名为MyObject"的程序集是从'file:///c:/MyObject/bin/Debug/MyObject.dll'使用 LoadFrom 上下文.使用此上下文可能会导致序列化、转换和依赖的意外行为解析度.在几乎所有情况下,建议 LoadFrom上下文被避免.这可以通过在全局程序集缓存或在 ApplicationBase 目录中并使用Assembly.Load 显式加载程序集时.

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 注册的.但随后:

Which I expected because it was registered using /CodeBase instead of using the GAC. But then:

显示名称为MyObject"的程序集无法加载到ID 为 1 的 AppDomain 的LoadFrom"绑定上下文.失败是: System.IO.FileNotFoundException: 无法加载文件或程序集 'MyObject, Version=1.0.0.0, Culture=neutral,PublicKeyToken=92a84ff3d67c82b9' 或其依赖项之一.这系统找不到指定的文件.

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、Load Image 等).看起来不是文件访问问题,而是框架进行了一些运行时检查.

The MyObject component (which loads perfectly if invoked from PHP) has no special dependencies (only .Net). Tracing from sysinternal's process monitor I couldn't see anything failing, and the access to my .dll is successful (CreateFileMapping, Load Image, etc.). It doesn't look like it is a file access problem but some runtime check made by the framework.

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

Both the test .net client and the COM+ component were compiled from the same compiler; all relevant options look the same (platform set to x86, .Net Framework 4). As an extra debugging measure I log the framework version to a file both in the component and in the test program, although they are the same (4.0.30319.34209). Everything is run on the same machine.

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

The Fusion log suggests that the runtime attempts to load the binary directly (without invoking the COM+ instance).

出于遗留原因,我需要这种扭曲的交互 (.Net-->COM+-->.Net),但我无法使其工作.会发生什么?

I need this twisted interaction (.Net-->COM+-->.Net) for legacy reasons, but I cannot make it work. What could be happening?

推荐答案

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

It turns out registration using RegAsm.exe is not the correct procedure for this operation. The assembly must be added to the GAC first and then the COM+ application must be created using the regsvcs utility. Otherwise, .Net doesn't look into the COM+ catalog at all:

"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

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

Note: the utilities' path may be different in your system.

这篇关于.Net 项目中的 .Net COM+:System.IO.FileNotFoundException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆