【问题标题】:IDispatch::Invoke Returning E_INVALIDARGIDispatch::Invoke 返回 E_INVALIDARG
【发布时间】:2014-08-21 13:15:39
【问题描述】:

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

【问题讨论】:

  • Reintepret_cast 而不是 QI for IDispatch 是错误的。
  • 我还要仔细检查 dispparams 的 vt 值。第一个参数应该是 IDispatch 吗?我希望索引以递增的顺序排列,而不是递减。
  • "UDT" 是一个危险信号,它需要在类型库中定义才能在来自 VT_RECORD 的转换中存活。
  • @EricBrown:我可以在其中扔一个QueryInterface,尝试一下不会有什么坏处,但我认为这不是手头的问题(此代码也是自动生成的)。我会检查 vt,但索引实际上是按降序排列的。请参阅msdn.microsoft.com/en-us/library/windows/desktop/…puArgErr [out] 部分。
  • @EricBrown:天哪!我将 VARIANT_BOOL 参数的 vt 更改为 11(VT_BOOL,duh),它起作用了!是的。感谢您的帮助,我真的很感激。发布答案以便我接受。

标签: c++ com interop


【解决方案1】:

仔细检查您的 dispparam 变体中的 vt 值;许多 IDispatch 实现都非常注重让所有内容都对齐。

【讨论】:

    猜你喜欢
    • 2021-03-23
    • 1970-01-01
    • 1970-01-01
    • 2013-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多