You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ActiveX混合BSTR与LONG参数事件调用失败排查求助

混合BSTR与LONG参数的ActiveX事件无法触发的问题排查

我有一个同时包含命令和事件的ActiveX应用,所有命令均能正常工作,但混合BSTR与LONG参数的事件无法被触发;仅含LONG参数或仅含BSTR参数的事件则运行正常。以下是关键代码片段:

.idl文件:

[id(1)] void onEvent1([in] LONG longParam1, [in] LONG longParam2);
[id(2)] void onEvent2([in] LONG longParam, [in] BSTR bstrParam);

事件调用代码:

virtual HRESULT Notify(DISPID dispIdMember, DISPPARAMS* params) override
{
    if (!params)
    {
        return S_FALSE;
    }

    HRESULT hr = S_OK;
    T* pThis = static_cast<T*>(this);

    for (int iConnection = 0; iConnection < m_vec.GetSize(); ++iConnection)
    {
        pThis->Lock();
        CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
        pThis->Unlock();

        if (IDispatch* pConnection = static_cast<IDispatch*>(punkConnection.p))
        {
            hr = pConnection->Invoke(dispIdMember, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, params, NULL, NULL, NULL);
        }
    }

    return hr;
}

HRESULT onEvent1(LONG longParam1, LONG longParam2)
{
    const UINT currentEventParamsSize{ 2 };

    CComVariant avarParams[currentEventParamsSize];

    avarParams[1] = longParam1;
    avarParams[1].vt = VT_I4;

    avarParams[0] = longParam2;
    avarParams[0].vt = VT_I4;

    DISPPARAMS params = { avarParams, NULL, currentEventParamsSize, 0 };

    return Notify(1, &params);
}

HRESULT onEvent2(LONG longParam, BSTR bstrParam)
{

    const UINT currentEventParamsSize{ 2 };

    CComVariant avarParams[currentEventParamsSize];
    avarParams[0] = longParam;
    avarParams[0].vt = VT_I4;
    avarParams[1] = bstrParam;
    avarParams[1].vt = VT_BSTR;

    DISPPARAMS params = { avarParams, NULL, currentEventParamsSize, 0 };

    return Notify(2, &params);
}

其中onEvent1可正常工作,但onEvent2无法触发,测试应用已完成全部重建/更新。


错误分析与修正

错误核心在于**onEvent2的参数顺序完全颠倒**,以及潜在的BSTR赋值细节问题:

  1. 参数顺序逻辑错误
    ActiveX事件通过DISPPARAMS传递参数时,rgvarg数组是逆序排列的:事件定义的第一个参数对应数组的最后一个元素,第二个参数对应数组的第一个元素。
  • onEvent1中你正确遵循了这个规则:把第一个参数longParam1放在avarParams[1],第二个参数longParam2放在avarParams[0],所以能正常触发。
  • onEvent2中你完全搞反了顺序:把第一个参数longParam放在avarParams[0],第二个参数bstrParam放在avarParams[1],导致参数类型与事件定义不匹配,最终无法触发。
  1. BSTR的Variant赋值优化
    直接用avarParams[1] = bstrParam虽然能工作,但建议使用CComVariant的Attach方法更安全,避免潜在的内存泄漏风险,不过这不是本次问题的核心原因。

修正后的onEvent2代码

HRESULT onEvent2(LONG longParam, BSTR bstrParam)
{
    const UINT currentEventParamsSize{ 2 };

    CComVariant avarParams[currentEventParamsSize];
    // 事件的第二个参数bstrParam对应数组索引0
    avarParams[0] = bstrParam;
    avarParams[0].vt = VT_BSTR;
    // 事件的第一个参数longParam对应数组索引1
    avarParams[1] = longParam;
    avarParams[1].vt = VT_I4;

    DISPPARAMS params = { avarParams, NULL, currentEventParamsSize, 0 };

    return Notify(2, &params);
}

补充说明

IDispatch::Invoke处理事件参数时,严格按照逆序匹配类型。onEvent1因为两个参数都是LONG类型,顺序颠倒后依然能匹配成功;但onEvent2混合了LONG和BSTR类型,类型不匹配会导致事件接收端无法识别,最终无法触发。

内容的提问来源于stack exchange,提问作者user2123079

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 22:45:38