IDispatch :: Invoke返回E_INVALIDARG

时间:2014-07-01 04:26:43

标签: c++ com interop

我有一个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专业人员之前遇到过这种情况。

1 个答案:

答案 0 :(得分:1)

仔细检查dispparam变体中的vt值;许多IDispatch实现都非常特别关注所有内容的排列。