1

しばらく前に答えた同様の質問に続いて、オブジェクトを列挙しようとすると、IE9での使用IDispatch::Invoke(DISPID_NEWENUM,...)が失敗することがわかりました。 これは、任意のjavascript配列のおよびで発生します。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;
}

特にIE9でDISP_E_EXCEPTIONのHRESULTを使用して、このコードが常に失敗する理由(IDispatchおよびIDispatchEx)を誰かが知っていますか?

ありがとう。

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 に答える