概述
我现在已经验证了eval方法与IE9,IE10和IE11一致(错误检查跳过了错误):
CComVariant result;
CComDispatchDriver disp = m_htmlWindow; // of IHTMLWindow2
disp.Invoke1(L"eval", &CComVariant(L"confirm('See this?')"), &result);
result.ChangeType(VT_BSTR);
MessageBoxW(V_BSTR(&result));
感觉比execScript更好,因为它实际上返回结果.
它也在C#与WinForms的WebBrowser工作:
var result = webBrowser1.Document.InvokeScript("eval", new object[] { "confirm('see this?')" });
MessageBox.Show(result.ToString());
也就是说,execScript仍然适用于IE11 Preview:
CComVariant result;
m_htmlWindow->execScript(CComBSTR(L"confirm('See this too?')"), CComBSTR(L"JavaScript"), &result);
result.ChangeType(VT_BSTR);
MessageBoxW(V_BSTR(&result));
它仍然像以前一样舍弃结果.
有点偏离主题,但是您不必坚持使用eval.此方法允许在加载的页面的JavaScript窗口对象的命名空间(通过IDispatch接口)中执行任何可用的命名方法.您可以调用自己的函数,并将一个COM对象传递给它,而不是一个字符串参数,例如:
// JavaScript
function AlertUser(user)
{
alert(user.name);
return user.age;
}
// C++
CComDispatchDriver disp = m_htmlWindow; // of IHTMLWindow2
disp.Invoke1(L"AlertUser", &CComVariant(userObject), &result);
我可能会喜欢上述直接调用eval.
[EDITED]
需要一些调整来使此方法适用于进程外调用.正如@JimEvans在评论中指出的那样,Invoke正在返回错误0x80020006(“未知名称”).不过,一个test HTA app的工作很好,是什么让我想到尝试IDispatchEx::GetDispId进行名称解析.确实有效(错误检查跳过):
CComDispatchDriver dispWindow;
htmlWindow->QueryInterface(&dispWindow);
CComPtr dispexWindow;
htmlWindow->QueryInterface(&dispexWindow);
DISPID dispidEval = -1;
dispexWindow->GetDispID(CComBSTR("eval"), fdexNameCaseSensitive, &dispidEval);
dispWindow.Invoke1(dispidEval, &CComVariant("function DoAlert(text) { alert(text); }")); // inject
DISPID dispidDoAlert = -1;
dispexWindow->GetDispID(CComBSTR("DoAlert"), fdexNameCaseSensitive, &dispidDoAlert) );
dispWindow.Invoke1(dispidDoAlert, &CComVariant("Hello, World!")); // call
[UPDATE]
此更新在子代码iframe的窗口对象上创建__execScript方法.要注入的代码被优化以返回目标窗口对象供以后使用(不需要进行一系列的out-of-proc调用来获取iframe对象,它在主窗口的上下文中完成):
CComBSTR __execScriptCode(L"(window.__execScript = function(exp) { return eval(exp); }, window.self)");
以下是C控制台应用程序(pastebin)的代码,错误地跳过了一些错误检查.还有一个相应的prototype in .HTA,更可读.
//
// https://stackoverflow.com/questions/18342200/how-do-i-call-eval-in-ie-from-c/18349546//
//
#include
#include
#include
#include
#include
#include
#define _S(a)
{ HRESULT hr = (a); if (FAILED(hr)) return hr; }
#define disp_cast(disp)
((CComDispatchDriver&)(void(static_cast(disp)), reinterpret_cast(disp)))
struct ComInit {
ComInit() { ::CoInitialize(NULL); }
~ComInit() { CoUninitialize(); }
};
int _tmain(int argc, _TCHAR* argv[])
{
ComInit comInit;
CComPtr ie;
_S( ie.CoCreateInstance(L"InternetExplorer.Application", NULL, CLSCTX_LOCAL_SERVER) );
_S( ie->put_Visible(VARIANT_TRUE) );
CComVariant ve;
_S( ie->Navigate2(&CComVariant(L"http://jsfiddle.net/"), &ve, &ve, &ve, &ve) );
// wait for page to finish loading
for (;;)
{
Sleep(250);
READYSTATE rs = READYSTATE_UNINITIALIZED;
ie->get_ReadyState(&rs);
if ( rs == READYSTATE_COMPLETE )
break;
}
// inject __execScript into the main window
CComPtr dispDoc;
_S( ie->get_Document(&dispDoc) );
CComPtr htmlDoc;
_S( dispDoc->QueryInterface(&htmlDoc) );
CComPtr htmlWindow;
_S( htmlDoc->get_parentWindow(&htmlWindow) );
CComPtr dispexWindow;
_S( htmlWindow->QueryInterface(&dispexWindow) );
CComBSTR __execScript("__execScript");
CComBSTR __execScriptCode(L"(window.__execScript = function(exp) { return eval(exp); }, window.self)");
DISPID dispid = -1;
_S( dispexWindow->GetDispID(CComBSTR("eval"), fdexNameCaseSensitive, &dispid) );
_S( disp_cast(dispexWindow).Invoke1(dispid, &CComVariant(__execScriptCode)) );
// inject __execScript into the child frame
WCHAR szCode[1024];
wsprintfW(szCode, L"document.all.tags("iframe")[0].contentWindow.eval("%ls")", __execScriptCode.m_str);
dispid = -1;
_S( dispexWindow->GetDispID(__execScript, fdexNameCaseSensitive, &dispid) );
CComVariant vIframe;
_S( disp_cast(dispexWindow).Invoke1(dispid, &CComVariant(szCode), &vIframe) ); // inject __execScript and return the iframe's window object
_S( vIframe.ChangeType(VT_DISPATCH) );
CComPtr dispexIframe;
_S( V_DISPATCH(&vIframe)->QueryInterface(&dispexIframe) );
dispid = -1;
_S( dispexIframe->GetDispID(__execScript, fdexNameCaseSensitive, &dispid) );
_S( disp_cast(dispexIframe).Invoke1(dispid, &CComVariant("alert(document.URL)")) ); // call the code inside child iframe
return 0;
}
最后
以上就是年轻睫毛为你收集整理的c 调用html方法,如何在C中调用eval()?的全部内容,希望文章能够帮你解决c 调用html方法,如何在C中调用eval()?所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复