1

在我前段时间回答的一个类似问题之后,我发现在尝试枚举对象时,在 IE9 上使用IDispatch::Invoke(DISPID_NEWENUM,...)失败。 这发生在任何 javascript 数组上的and上。DISP_E_EXCEPTION
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),HRESULT 为 DISP_E_EXCEPTION,特别是在 IE9 上?

谢谢。

4

2 回答 2

3
 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;
}
于 2012-02-27T10:45:23.310 回答
1

IEnumVARIANT 可能会起作用。虽然当我尝试它时 IEnumVARIANT::Next 总是返回 E_FAIL,但该元素被正确获取。没有时间或需要深入了解这一点。

它对我有用,但如果不是,我打算使用 IDispatchEx:当 IE 传递数组对象的枚举成员时,它们都有“0”、“1”等,但不是“长度”方法,但必须是在它的typeinfo中,没有检查。我想你应该已经明白了。

抱歉,如果不遵循一些特殊的格式规则,这个网站不允许我发布伪代码

hth

于 2011-08-10T22:13:52.613 回答