使用 C++ 检索 javascript 数组对象在 IE9 上使用 DISPID_NEWENUM 失败

发布于 2024-11-18 06:30:51 字数 1513 浏览 9 评论 0原文

在我不久前回答过的类似问题之后,我发现尝试枚举对象时,使用 IDispatch::Invoke(DISPID_NEWENUM,...) 失败,并显示 DISP_E_EXCEPTION on IE9。
在任何 javascript 数组上,IDispatchIDispatchEx 都会发生这种情况。

不用说,该代码在 IE6-IE8 上运行良好,但仅在 IE9 上失败。

同样的问题也出现在 MSDN 开发论坛 到目前为止还没有运气。

这是一个代码片段来演示我尝试做的事情。请注意,pDispatch 是 javascript 的数组变体。

// invoke the object to retrieve the enumerator containing object
CComVariant varResult;

DISPPARAMS dispparamsNoArgs = {0};
EXCEPINFO excepInfo = {0};
UINT uiArgErr = (UINT)-1;  // initialize to invalid arg
HRESULT hr = pDispatch->Invoke(DISPID_NEWENUM, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD | DISPATCH_PROPERTYGET, &dispparamsNoArgs, &varResult, &excepInfo, &uiArgErr);

// if failed - retry with IDispatchEX
if (FAILED(hr))
{
   CComPtr<IDispatchEx> pDispatchEx;
   pDispatchEx = pDispatch; // Implied query interface

   hr = pDispatchEx->InvokeEx(DISPID_NEWENUM, LOCALE_USER_DEFAULT, DISPATCH_METHOD | DISPATCH_PROPERTYGET, &dispparamsNoArgs, &varResult, &excepInfo, NULL);

   if (FAILED(hr))
      return false;
}

有谁知道为什么此代码总是失败(IDispatch 和 IDispatchEx),特别是在 IE9 上,HRESULT 为 DISP_E_EXCEPTION?

谢谢。

following a similar question i answered some time ago, i found out that when trying to enumerate the object, using IDispatch::Invoke(DISPID_NEWENUM,...) fails with DISP_E_EXCEPTION on IE9.
This happens with IDispatch and IDispatchEx, on any javascript array.

needless to say that the code works great on IE6-IE8, and fails only on IE9.

The same question also appears in the MSDN dev forums with no luck so far.

Here's a code snippet to demonstrate what I tried to do. notice that pDispatch is the javascript's array variant.

// invoke the object to retrieve the enumerator containing object
CComVariant varResult;

DISPPARAMS dispparamsNoArgs = {0};
EXCEPINFO excepInfo = {0};
UINT uiArgErr = (UINT)-1;  // initialize to invalid arg
HRESULT hr = pDispatch->Invoke(DISPID_NEWENUM, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD | DISPATCH_PROPERTYGET, &dispparamsNoArgs, &varResult, &excepInfo, &uiArgErr);

// if failed - retry with IDispatchEX
if (FAILED(hr))
{
   CComPtr<IDispatchEx> pDispatchEx;
   pDispatchEx = pDispatch; // Implied query interface

   hr = pDispatchEx->InvokeEx(DISPID_NEWENUM, LOCALE_USER_DEFAULT, DISPATCH_METHOD | DISPATCH_PROPERTYGET, &dispparamsNoArgs, &varResult, &excepInfo, NULL);

   if (FAILED(hr))
      return false;
}

Does anyone have any idea why this code always fails (IDispatch and IDispatchEx) with HRESULT of DISP_E_EXCEPTION specifically on IE9?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

眼趣 2024-11-25 06:30:51
 IDispatch *disp = pszBufData->pdispVal;
if (pszBufData->vt & VT_BYREF)
    disp = *(pszBufData->ppdispVal);

// Get IDispatchEx on input IDispatch
CComQIPtr<IDispatchEx> pdispexArray(disp);
if ( ! pdispexArray )
    return E_NOINTERFACE;

// Get array length DISPID
DISPID dispidLength;
CComBSTR bstrLength(L"length");
HRESULT hr = pdispexArray->GetDispID(bstrLength, fdexNameCaseSensitive, &dispidLength);
if (FAILED(hr))
    return false;

 // Get length value using InvokeEx()
CComVariant varLength;
DISPPARAMS dispParamsNoArgs = {0};
hr = pdispexArray->InvokeEx(dispidLength, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispParamsNoArgs, &varLength, 
    NULL, NULL);
if (FAILED(hr))
    return hr;

ATLASSERT(varLength.vt == VT_I4);
const int count = varLength.intVal;

BYTE * pData = new BYTE[count];

// For each element in source array:
for (int i = 0; i < count; i++)
{
    CString strIndex;
    strIndex.Format(L"%d", i);

    // Convert to BSTR, as GetDispID() wants BSTR's
    CComBSTR bstrIndex(strIndex);
    DISPID dispidIndex;
    hr = pdispexArray->GetDispID(bstrIndex, fdexNameCaseSensitive, &dispidIndex);
    if (FAILED(hr))
        break;

    // Get array item value using InvokeEx()
    CComVariant varItem;
    hr = pdispexArray->InvokeEx(dispidIndex, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispParamsNoArgs, &varItem, 
        NULL, NULL);
    if (FAILED(hr))
        break;

    ATLASSERT(varItem.vt == VT_I4);

    pData[i] = varItem.intVal;
}
 IDispatch *disp = pszBufData->pdispVal;
if (pszBufData->vt & VT_BYREF)
    disp = *(pszBufData->ppdispVal);

// Get IDispatchEx on input IDispatch
CComQIPtr<IDispatchEx> pdispexArray(disp);
if ( ! pdispexArray )
    return E_NOINTERFACE;

// Get array length DISPID
DISPID dispidLength;
CComBSTR bstrLength(L"length");
HRESULT hr = pdispexArray->GetDispID(bstrLength, fdexNameCaseSensitive, &dispidLength);
if (FAILED(hr))
    return false;

 // Get length value using InvokeEx()
CComVariant varLength;
DISPPARAMS dispParamsNoArgs = {0};
hr = pdispexArray->InvokeEx(dispidLength, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispParamsNoArgs, &varLength, 
    NULL, NULL);
if (FAILED(hr))
    return hr;

ATLASSERT(varLength.vt == VT_I4);
const int count = varLength.intVal;

BYTE * pData = new BYTE[count];

// For each element in source array:
for (int i = 0; i < count; i++)
{
    CString strIndex;
    strIndex.Format(L"%d", i);

    // Convert to BSTR, as GetDispID() wants BSTR's
    CComBSTR bstrIndex(strIndex);
    DISPID dispidIndex;
    hr = pdispexArray->GetDispID(bstrIndex, fdexNameCaseSensitive, &dispidIndex);
    if (FAILED(hr))
        break;

    // Get array item value using InvokeEx()
    CComVariant varItem;
    hr = pdispexArray->InvokeEx(dispidIndex, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispParamsNoArgs, &varItem, 
        NULL, NULL);
    if (FAILED(hr))
        break;

    ATLASSERT(varItem.vt == VT_I4);

    pData[i] = varItem.intVal;
}
很糊涂小朋友 2024-11-25 06:30:51

IEnumVARIANT 可能有效。
虽然当我尝试 IEnumVARIANT::Next 时总是返回 E_FAIL,
元素已正确获取。没有时间也没有必要追根究底。

它对我有用,但如果没有,我打算使用 IDispatchEx:
当IE传递的数组对象的枚举成员时,它们都有“0”,“1”等......,但不是“length”方法,必须在它的类型信息中,尚未检查。
我想你明白了。

该网站将不允许我发布伪代码

抱歉,无法发布伪代码,如果不遵循一些特殊的格式规则,

IEnumVARIANT may work.
Although when I tried it IEnumVARIANT::Next always was returning E_FAIL,
the element was fetched correctly. Didn't have time or need to get to the bottom of this.

It worked for me, but if it didn't I was intended to use IDispatchEx:
when enumerated members of array objects passed by IE they all had "0", "1" etc.., not "length" method though, must be in it's typeinfo, haven't checked.
I think you get the idea.

Sorry can't post pseudo code this site won't allow me without following some special formatting rules

hth

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文