我有一个必须使用 COM 插件的 ASP.NET MVC3 网站。为了做到这一点,我需要以某种方式定义一个接口。据我了解(我不是 COM 专家),这可以在 .NET 中完成并使用 tlbexp.exe 或 idl->midl->tlbimp 导出。
我走了第一种方式(使用 tlbexp)。我也尝试过 IDL,但无济于事(出于某种原因,可能会将实现的 COM 对象转换回 .NET 中的 tlbimp 接口)。
如果我的界面上没有事件,这种情况会很简单:
[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);
}
我使用 tlbexp.exe 将其导出到 tlb,并使用 regtlibv12 注册 .tlb。插件开发人员将仅使用此类型库来导入接口。
现在我有一个 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 对象:
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 端错误地订阅事件还是添加处理程序?
任何帮助如何解决这个问题将不胜感激。