VARIANT ExecuteScript(IWebBrowser2 *pWebBrowser, const SStringW & fun,SArray<SStringW> & params) { VARIANT varErr; VariantInit( &varErr ); //get document dispatch interface IDispatch* pDisp = NULL; HRESULT hr = pWebBrowser->get_Document( &pDisp ); if ( FAILED( hr ) || pDisp == NULL ) { return varErr; } IHTMLDocument2* pDoc = NULL; pDisp->QueryInterface( IID_IHTMLDocument2,(void**)&pDoc ); pDisp->Release(); IDispatch* pScript = NULL; hr = pDoc->get_Script( &pScript ); pDoc->Release(); if ( FAILED( hr ) || pScript == NULL ) { return varErr; } sbstr bstrMember((int)fun.GetLength(),fun ); DISPID dispid = 0; BSTR bstr = (BSTR)bstrMember; hr = pScript->GetIDsOfNames( IID_NULL,&(bstr),1,LOCALE_SYSTEM_DEFAULT,&dispid ); if ( FAILED( hr ) ) { return varErr; } DISPPARAMS dispparams; ::ZeroMemory( &dispparams,sizeof( DISPPARAMS ) ); dispparams.cArgs = (UINT)params.GetCount(); dispparams.rgvarg = new VARIANT[dispparams.cArgs]; dispparams.cNamedArgs = 0; for ( size_t i = 0;i < params.GetCount();i++ ) { size_t indx = params.GetCount() - i - 1; sbstr bstrParam((int)params[indx].GetLength(),params[indx]); dispparams.rgvarg[i].bstrVal = bstrParam.Release(); dispparams.rgvarg[i].vt = VT_BSTR; } EXCEPINFO excepinfo; ::ZeroMemory( &excepinfo,sizeof( EXCEPINFO ) ); VARIANT varRet; UINT nArgErr = (UINT)-1; //initialize to invalid arg hr = pScript->Invoke( dispid,IID_NULL,0,DISPATCH_METHOD,&dispparams,&varRet,&excepinfo,&nArgErr ); delete []dispparams.rgvarg; pScript->Release(); if ( FAILED( hr ) ) { return varErr; } return varRet; }
// thanks to Eugene Khodakovsky (I've just modified his code to make more lazy script call) BOOL CHtmlViewer::ExecScript(TCHAR* ScriptContent,VARIANT* pScriptResult,EXCEPINFO* pExcepInfo) { HRESULT hr = S_OK; IDispatch* pHtmlDocDispatch = NULL; IHTMLDocument2* pHtmlDoc = NULL; DISPID dispid = NULL; BSTR bstrMember; IDispatch* spScript; if (IsBadWritePtr(pExcepInfo,sizeof(EXCEPINFO))) return FALSE; memset(pExcepInfo, 0, sizeof(EXCEPINFO)); pScriptResult->vt=VT_EMPTY; // Retrieve the document object. hr = pIWebBrowser->get_Document(&pHtmlDocDispatch); if (SUCCEEDED (hr) && (pHtmlDocDispatch != NULL)) { hr = pHtmlDocDispatch->QueryInterface(IID_IHTMLDocument2,(void**)&pHtmlDoc); if (SUCCEEDED (hr) && (pHtmlDoc != NULL)) { //Getting IDispatch for Java Script objects hr = pHtmlDoc->get_Script(&spScript); if (SUCCEEDED (hr) && (spScript != NULL)) { bstrMember=SysAllocString(L"eval");// THE trick is here if (bstrMember) { hr = spScript->GetIDsOfNames(IID_NULL,&bstrMember,1,LOCALE_SYSTEM_DEFAULT,&dispid); if (SUCCEEDED (hr)) { //Putting parameters DISPPARAMS dispparams; memset(&dispparams, 0, sizeof (DISPPARAMS)); dispparams.cArgs = 1; dispparams.rgvarg = new VARIANT[dispparams.cArgs]; dispparams.cNamedArgs = 0; dispparams.rgvarg[0].vt = VT_BSTR; WCHAR* wScriptContent; #if (defined(UNICODE)||defined(_UNICODE)) wScriptContent=ScriptContent; #else CAnsiUnicodeConvert::AnsiToUnicode(ScriptContent,&wScriptContent); #endif dispparams.rgvarg[0].bstrVal = SysAllocString(wScriptContent); #if ((!defined(UNICODE))&& (!defined(_UNICODE))) free(wScriptContent); #endif /* // code for those who want to do the same thing // using an array of string "const CStringArray& paramArray" as parameter // instead of eval tips const int arraySize = paramArray.GetSize(); //Putting parameters DISPPARAMS dispparams; memset(&dispparams, 0, sizeof dispparams); dispparams.cArgs = arraySize; dispparams.rgvarg = new VARIANT[dispparams.cArgs]; dispparams.cNamedArgs = 0; for( int i = 0; i < arraySize; i++) { CComBSTR> bstr = paramArray.GetAt(arraySize - 1 - i); // back reading bstr.CopyTo(&dispparams.rgvarg[i].bstrVal); dispparams.rgvarg[i].vt = VT_BSTR; } */ if (dispparams.rgvarg[0].bstrVal) { UINT nArgErr = (UINT)-1;// initialize to invalid arg //Call JavaScript function hr = spScript->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, &dispparams, pScriptResult, pExcepInfo, &nArgErr); SysFreeString(dispparams.rgvarg[0].bstrVal); } delete [] dispparams.rgvarg; } SysFreeString(bstrMember); } } pHtmlDoc->Release(); } pHtmlDocDispatch->Release(); } return SUCCEEDED (hr); }