JScript数组上的IDispatch::Invoke_NewEnum在IE9中不起作用

IDispatch::Invoke _NewEnum on JScript Array not working in IE9

本文关键字:NewEnum IE9 不起作用 Invoke 数组 IDispatch JScript      更新时间:2023-09-26

我有一个ActiveX组件,它从javascript接收字节数组并对其进行处理;8,但在IE 9中,当我调用IDispatch::Invoke时它失败了,请帮助我解决

if(pszBufData->vt == VT_DISPATCH)
        {       
            BYTE * pData = new BYTE[dwSize];
            IDispatch *pDisp = pszBufData->pdispVal;
            pDisp->AddRef();
            DISPPARAMS dispparamsNoArgs = { NULL, NULL, 0, 0 };
            VARIANT var;
            VariantInit(&var);
            HRESULT hr = pDisp->Invoke(DISPID_NEWENUM, IID_NULL, GetUserDefaultLCID(), DISPATCH_PROPERTYGET, &dispparamsNoArgs, &var, NULL, NULL);

            int i=0;
            if (SUCCEEDED(hr)) 
            {
             if (var.vt == VT_UNKNOWN) 
             {
                 IEnumVARIANT *pEnum = NULL;
                 if SUCCEEDED(var.punkVal->QueryInterface(IID_IEnumVARIANT, (void**) &pEnum)) 
                 {
                     VARIANT item;
                     VariantInit(&item);
                     pEnum->Reset();
                     while ( (pEnum->Next(1, &item, NULL) && S_FALSE) != S_FALSE) 
                     {                   
                         if (item.vt == VT_I4) 
                         {  
                             //AfxMessageBox(_T("SendData"));
                             pData[i] = item.cVal;
                             i++;
                         }
                         VariantClear(&item);
                     }
                     pEnum->Release();
                 }
                   var.punkVal->Release();
             }
            }
            /*VariantClear(&var);*/
            pDisp->Release();

        }

java脚本代码

<HTML>
<HEAD>
    <SCRIPT LANGUAGE="JavaScript" FOR="window" EVENT="onLoad()">
<!--
var arr = new Array(0x1, 0xA,0x20)
//CSDS_Communication1.ConfigCon("COM1",9600)
CSDS_Communication1.SendData("COM1",arr,3)

-->
    </SCRIPT>
<TITLE>New Page</TITLE>
</HEAD>
<BODY>
    <OBJECT ID="CSDS_Communication1" WIDTH=100 HEIGHT=51
     CLASSID="CLSID:73D79990-090E-48CB-8857-E6BF50F42E63">
        <PARAM NAME="_Version" VALUE="65536">
        <PARAM NAME="_ExtentX" VALUE="2646">
        <PARAM NAME="_ExtentY" VALUE="1323">
        <PARAM NAME="_StockProps" VALUE="0">
    </OBJECT>
</BODY>
</HTML>

使用以下代码修复了该问题固定代码

    BYTE * pData = new BYTE[dwSize];
    /* retrieving IDispatch */
    IDispatch *disp = pszBufData->pdispVal;
    if (pszBufData->vt & VT_BYREF)
        disp = *(pszBufData->ppdispVal);
    /* getting array's length */
    DISPPARAMS params;
    FillMemory(&params, sizeof(DISPPARAMS), 0);
    VARIANT res;
    DISPID dl = 0;
    LPOLESTR ln = L"length";
    HRESULT hr = disp->GetIDsOfNames(IID_NULL, &ln, 1, LOCALE_USER_DEFAULT, &dl);
    if (FAILED(hr))
        return false;
    // get the number of elements using the DISPID of length parameter
    hr =disp->Invoke(dl, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,&params, &res, NULL, NULL);
    if (FAILED(hr))
        return false;

    VARIANT len1;
    VariantInit(&len1);
    VariantChangeType(&len1, &res, 0, VT_I4);
    LONG len = len1.lVal;
    /* summing elements */
    for (int i = 0; i < len; i++)
    {
        std::wstring strIndex;// = StringUtils::IntToString(i);
        wchar_t buf[8];
        _itow(i,buf,10);
        strIndex.append(buf);
        DISPID dispid;
        LPOLESTR pIndex = reinterpret_cast<LPOLESTR>(const_cast<WCHAR *>(strIndex.data()));

        hr = disp->GetIDsOfNames( IID_NULL, &pIndex, 1, LOCALE_USER_DEFAULT, &dispid );
         if (FAILED(hr))
             continue;

        /*std::stringstream ss;
        ss << ind =" CComBSTR(ss.str().c_str());">GetIDsOfNames(IID_NULL, &ind, 1, LOCALE_USER_DEFAULT, &dispid));*/
        hr = disp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &params, &res, NULL, NULL);
        if (FAILED(hr))
             continue;
        VARIANT val1;
        VariantInit(&val1);
        VariantChangeType(&val1, &res, 0, VT_I4);
        pData[i] = val1.lVal;

    }

第2次错误:

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;
    }

我认为您对问题的诊断是错误的。标题应该是:jscript9不支持数组对象的NewEnum。如果有什么不同的话,我很惊讶它在以前的版本上对你有效-我没有尝试过,但在IE9(jscript9.dll)上,无论是SAFEARRAY还是IEnumVeriant和任何其他Array构造都无法访问JavaScript数组。Javascript数组不过是普通的IDispatchEx对象。您可以访问作为"0"、"1"answers"2"的各个项目。

Eric Lippert的以下帖子解释了JavaScript数组:http://blogs.msdn.com/b/ericlippert/archive/2003/09/22/53061.aspx

在C++代码中,使用指向IDispatch的pDisp指针执行以下操作(第一个元素的伪代码):

DISPID dispid;
wchar_t name[] = L"0";
pDisp->GetIDsOfNames( IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispid );
pDisp->Invoke( dispid, ... );

这是非常JavaScript'的东西。VBScript将传递一个完全不同的构造(可能是SAFEARRAY)。如果您使用pDisp->GetTypeInfo,并使用ITypeInfo::GetTypeAttr来获取有关类型的信息,那么您可以确切地调查您在pDisp中得到的内容。TYPEATTR.cVars返回属性的数量,GetVarDesc返回关于每个变量的信息。请验证是否没有"Length"、"Count"或_NewEnum变量,而您可以提取"0"、"1"、"2"变量。