2014-07-01 33 views
0

我有一个ATL COM组件引发了一些由托管(C#和VB.NET)代码处理的事件。该组件当前由VS2005 VB.NET项目(作为ActiveX控件)使用,并且引发所有事件并且一切正常。IDispatch :: Invoke正在返回E_INVALIDARG

但是,在将一些代码移植到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

Reintepret_cast代替Qis for IDispatch是错误的。 –

+0

我也会仔细检查distarams的vt值。第一个参数是否应该是IDispatch?我预计指数会按升序排列,而不是下降。 –

+0

“UDT”是一个红色标记,需要在类型库中定义,以便在从VT_RECORD转换后继续存在。 –

回答

1

仔细检查你的vt值在你的dispparam变种;许多IDispatch的实现对于让所有东西排列都非常特别。

相关问题