1

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.

Community
  • 1
  • 1
Bagelzone Ha'bonè
  • 1,192
  • 1
  • 14
  • 29

2 Answers2

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;
}
Jeeva
  • 4,585
  • 2
  • 32
  • 56
  • wait... jscript indexing takes bstr, not integer indices? it needs to convert it every time? – Dmytro Mar 26 '18 at 22:07
1

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

edp
  • 26
  • 1
  • do you mean that you got an IDispatch object (as an IE javascript array object) and when trying to retrieve it's IEnumVARIANT interface - you succeeded? because if you're using IE9 - it should fail. take a look at the code in my post - did you try the same method? thanks – Bagelzone Ha'bonè Aug 11 '11 at 07:24
  • yes, QueryInterface on IEnumVARIANT worked. My IE is 9.0.8112.16421 – edp Aug 11 '11 at 20:32
  • My IE most likely outdated. Won't be surprised if it fails in subsequent IE updates. Either IEnumVARIANT::Next or QueryInterface for IEnumVARIANT should be fixed. For release code I'd probably try using pDipstacheEx->GetDispID of "0", "1" etc. and then InvokeEx. – edp Aug 11 '11 at 20:59
  • that's what i ended up doing anyway. i was looking for a better alternative :) thanks – Bagelzone Ha'bonè Aug 13 '11 at 19:46