我有一个ATL COM组件,它引发了一些由托管(C#和VB.NET)代码处理的事件。该组件当前由VS2005 VB.NET项目(作为ActiveX控件)使用,所有事件都被引发,一切正常。
但是,在将一些代码移植到C#时,我注意到除了一个事件之外的所有事件都没有被引发。引发的唯一事件不会将参数传递回处理程序。所有其他人都这样做。
// this function is auto-generated
HRESULT Fire_SomeEvent(VARIANT_BOOL inOriginated, IUserType * inUserType)
{
CComVariant varResult;
T* pT = static_cast<T*>(this);
int nConnectionIndex;
CComVariant* pvars = new CComVariant[2];
int nConnections = m_vec.GetSize();
for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
{
pT->Lock();
CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
pT->Unlock();
IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
if (pDispatch != NULL)
{
VariantClear(&varResult);
pvars[1] = inOriginated;
pvars[0] = inUserType;
DISPPARAMS disp = { pvars, NULL, 2, 0 };
pDispatch->Invoke(0x7, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
}
}
delete[] pvars;
return varResult.scode;
}
Invoke
正在返回0x80070057 (E_INVALIDARG)
。然而,在VB领域,当通过ActiveX包装器使用时,它可以工作。现在,我无论如何都没有COM向导,我只是没有得到它。我无法在任何地方找到适用的东西。
我认为也许它与传递UDT有关,但是没有;一个几乎完全相同的版本,IUserType
替换为LONG
也会返回E_INVALIDARG
。同样,没有参数传递的单个事件也可以。
托管代码如何使用它的简短示例。这里没什么了不起的。
class Program
{
private ComType _c;
static void Main(string[] args)
{
_c = new ComType();
_c.SomeEvent += _c_SomeEvent;
_c.DoSomethingWhichRaisesSomeEvent();
}
static void _c_SomeEvent(bool b, IUserType udt)
{
// never called
}
}
我通常会在到达这里之前花更多的时间进行调试,但我必须尽快打电话。我要么必须解决这个问题,要么放弃这个接口并使用另一个接口(这对我来说是次优的)。所以,希望你们中的一些COM专业人员之前遇到过这种情况。
答案 0 :(得分:1)
仔细检查dispparam变体中的vt值;许多IDispatch实现都非常特别关注所有内容的排列。