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, ¶ms); } 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, ¶ms); }
其中onEvent1可正常工作,但onEvent2无法触发,测试应用已完成全部重建/更新。
错误分析与修正
错误核心在于**onEvent2的参数顺序完全颠倒**,以及潜在的BSTR赋值细节问题:
- 参数顺序逻辑错误
ActiveX事件通过DISPPARAMS传递参数时,rgvarg数组是逆序排列的:事件定义的第一个参数对应数组的最后一个元素,第二个参数对应数组的第一个元素。
onEvent1中你正确遵循了这个规则:把第一个参数longParam1放在avarParams[1],第二个参数longParam2放在avarParams[0],所以能正常触发。onEvent2中你完全搞反了顺序:把第一个参数longParam放在avarParams[0],第二个参数bstrParam放在avarParams[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, ¶ms); }
补充说明
IDispatch::Invoke处理事件参数时,严格按照逆序匹配类型。onEvent1因为两个参数都是LONG类型,顺序颠倒后依然能匹配成功;但onEvent2混合了LONG和BSTR类型,类型不匹配会导致事件接收端无法识别,最终无法触发。
内容的提问来源于stack exchange,提问作者user2123079
相关产品推荐
相关产品推荐

