У меня есть веб-сайт ASP.NET MVC3, который должен работать с COM-плагинами. Для этого мне нужно каким-то образом определить интерфейс. Насколько я понимаю (я не эксперт COM) это можно сделать либо в .NET, либо экспортировать его с помощью tlbexp.exe или idl-> midl-> tlbimp.COM-интерфейс .net plugin framework
Я пошел первым путем (с tlbexp). Я тоже пробовал IDL, но безрезультатно (по какой-то причине он мог применить реализованный COM-объект к интерфейсу tlbimp' в .NET).
Этот сценарий был бы простым, если мой интерфейс не есть событие на нем:
[ComVisible(true)]
[Guid("EFCFB783-0225-4D45-94CB-9A26B7CC19AF")]
public delegate void ItemStatusChanged(string itemGuid, string itemStatus);
[ComVisible(true)]
[Guid("35202AE5-392D-4015-993D-29966DA5DE31")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface ICOMOutputPlugin
{
void Method1(string arg);
void Method2(string arg);
event ItemStatusChanged ItemStatusChanged;
}
[ComVisible(true)]
[Guid("93862C43-503C-4C96-9BAE-944F1087AB77")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ICOMOutputPluginEvents
{
void ItemStatusChanged(string itemGuid, string itemStatus);
}
экспортировать это в TLB с Tlbexp.exe и зарегистрировать .TLB с regtlibv12. Только библиотека этого типа будет использоваться разработчиками плагинов для импорта интерфейсов.
Теперь у меня есть проект C++, который будет плагин, добавить в VS2010 новый объект простой ATL и изменить IDL на:
importlib("stdole2.tlb");
importlib("MyExp.tlb");
[
uuid(E09BC67A-4192-4CA3-8FD0-5CBFC69B43AC)
]
coclass DumpToFileOutputPlugin
{
[default] interface ICOMOutputPlugin;
[default, source] dispinterface ICOMOutputPluginEvents;
};
Моя первая проблема здесь в том, что по какой-то причине я не мог добавьте точку подключения «обычный путь» с помощью мастера классов. Он просто не показывает никаких исходных интерфейсов, когда я направляю его на MyExp.tlb. Поэтому я сделал это вручную (использовал другой .tlb и переименовал все).
Так что теперь у меня есть COM-объект с этими 2 методами:
STDMETHOD(add_ItemStatusChanged)(_ItemStatusChanged* value);
STDMETHOD(remove_ItemStatusChanged)(_ItemStatusChanged* value);
На стороне .NET менеджер плагин конкретизирует плагины, как это:
Type type = Type.GetTypeFromProgID(progID);
comObject = Activator.CreateInstance(type) as ICOMOutputPlugin;
comObject.ItemStatusChanged += (guid, status) => ItemStatusChanged(guid, status);
последняя строка чудесным образом называет add_ItemStatusChanged
способ на моем COM-объекте.
Здесь я застрял, что я должен использовать в этом методе? моя текущая реализация:
HRESULT CDumpToFileOutputPlugin::add_ItemStatusChanged(_ItemStatusChanged* value)
{
DWORD cookie;
HRESULT ret = Advise(value, &cookie);
_com_error err(ret);
LPCTSTR errMsg = err.ErrorMessage();
return ret;
}
RET = CONNECT_E_CANNOTCONNECT (0x80040202) и ERRMSG говорит "IDispatch ошибки # 2". Очевидно, Advise ожидает, что COM-объект передан для реализации интерфейса точки подключения ICOMOutputPluginEvents
, который передал делегат объекту ... что я могу сделать?
Я делаю подписку на событие на стороне .NET неправильно или обработчик добавления?
Любая помощь, как решить эту проблему, будет оценена по достоинству.
моя проблема не имеет ничего общего с ASP.NET, это просто проблема COM-взаимодействия, любое другое приложение .net будет делать, чтобы проиллюстрировать проблему – Bond
@Bond, вам не хватает точки. Вам не нужны события. Вы просто не нуждаетесь в них, поэтому избегайте проблемы взаимодействия COM, НЕ ИСПОЛЬЗУЯ СОБЫТИЯ. Просто выполняйте функции с EVENT-LIKE NAMES и вызывайте их, когда происходит событие. Это связано с тем, что COM-события являются РАЗЛИЧНЫМИ BEASTS и являются болью для подключения к ASP.NET, как вы только что узнали. – Ben
Тот факт, что tlbexp экспортирует событие в пару метода добавления/удаления и эти методы вызывается, когда я подписываюсь на событие на стороне .NET, заставляет меня думать, что должен быть какой-то способ заставить его работать. – Bond