Я написал компонент .Net, который работает в приложении COM +. Компонент наследуется от 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, я получаю исключение «Невозможно создать компонент ActiveX»:
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:
Сборка с именем MyObject была загружена из файла: /// c: /MyObject/bin/Debug/MyObject.dll с использованием контекста LoadFrom. Использование этого контекста может привести к неожиданному поведению при сериализации, приведении типов и разрешении зависимостей. Практически во всех случаях рекомендуется избегать контекста LoadFrom. Это можно сделать, установив сборки в глобальном кэше сборок или в каталоге ApplicationBase и используя Assembly.Load при явной загрузке сборок.
Чего я и ожидал, потому что он был зарегистрирован с использованием / CodeBase вместо использования GAC. Но потом:
Сборке с отображаемым именем MyObject не удалось загрузить в контексте привязки LoadFrom домена приложения с идентификатором 1. Причина сбоя: System.IO.FileNotFoundException: не удалось загрузить файл или сборку MyObject, версия = 1.0 .0.0, Культура = нейтральный, PublicKeyToken = 92a84ff3d67c82b9 'или одна из его зависимостей. Система не может найти указанный файл.
Компонент MyObject (который отлично загружается при вызове из PHP) не имеет особых зависимостей (только .Net). При отслеживании с помощью монитора процессов sysinternal я не видел, чтобы что-то выходило из строя, и доступ к моей .dll прошел успешно (CreateFileMapping, Load Image и т. Д.). Не похоже, что это проблема доступа к файлу, но некоторая проверка во время выполнения, сделанная фреймворком.
И тестовый клиент .net, и компонент COM + были скомпилированы из одного компилятора; все соответствующие параметры выглядят одинаково (платформа установлена на x86, .Net Framework 4). В качестве дополнительной меры отладки я записываю версию фреймворка в файл как в компоненте, так и в тестовой программе, хотя они одинаковы (4.0.30319.34209). Все работает на одной машине.
Журнал Fusion предполагает, что среда выполнения пытается загрузить двоичный файл напрямую (без вызова экземпляра COM +).
Мне нужно это запутанное взаимодействие (.Net -> COM + ->. Net) по устаревшим причинам, но я не могу заставить его работать. Что могло случиться?