Получить объект массива JavaScript с помощью C ++ с помощью DISPID_NEWENUM не удается в IE9 - PullRequest
1 голос
/ 03 июля 2011

после подобного вопроса я ответил некоторое время назад, я обнаружил, что при попытке перечислить объект использование IDispatch::Invoke(DISPID_NEWENUM,...) завершается неудачно с DISP_E_EXCEPTION в IE9.
Это происходит с IDispatch и IDispatchEx, на любом массиве JavaScript.

Само собой разумеется, что код отлично работает на IE6-IE8 и не работает только на IE9.

Тот же вопрос также появляется на форумах MSDN dev , не повезлодо сих пор.

Вот фрагмент кода, демонстрирующий то, что я пытался сделать.обратите внимание, что 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?

Спасибо.

Ответы [ 2 ]

3 голосов
/ 27 февраля 2012
 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;
}
1 голос
/ 11 августа 2011

IEnumVARIANT может работать. Хотя, когда я пытался это сделать, IEnumVARIANT :: Next всегда возвращал E_FAIL, элемент был выбран правильно. Не было времени или необходимости докопаться до этого.

Это сработало для меня, но если это не так, я собирался использовать IDispatchEx: когда перечислимые члены объектов массива, переданные IE, все они имели "0", "1" и т. д., а не метод "length", хотя, должны быть в его typeinfo, не проверяли. Я думаю, вы поняли.

Извините, я не могу опубликовать псевдокод, который не разрешит мне этот сайт без соблюдения некоторых специальных правил форматирования

НТН

...