.Net COM+ из проекта.Net: System.IO.FileNotFoundException
Я написал компонент.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" была загружена из "file:///c:/MyObject/bin/Debug/MyObject.dll" с использованием контекста LoadFrom. Использование этого контекста может привести к неожиданному поведению для сериализации, приведения и разрешения зависимостей. Практически во всех случаях рекомендуется избегать контекста LoadFrom. Это можно сделать, установив сборки в глобальный кэш сборок или в каталог ApplicationBase и используя Assembly.Load при явной загрузке сборок.
Что я ожидал, потому что он был зарегистрирован с использованием /CodeBase вместо GAC. Но потом:
Не удалось загрузить сборку с отображаемым именем "MyObject" в контексте привязки "LoadFrom" AppDomain с идентификатором 1. Причина сбоя: System.IO.FileNotFoundException: Не удалось загрузить файл или сборку "MyObject, Version=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) по старым причинам, но я не могу заставить его работать. Что может происходить?
1 ответ
Оказывается, регистрация с использованием RegAsm.exe не является правильной процедурой для этой операции. Сборка должна быть сначала добавлена в GAC, а затем приложение COM+ должно быть создано с помощью утилиты regsvcs. В противном случае.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
Примечание: путь к утилитам может отличаться в вашей системе.