c 调用html方法,如何在C中调用eval()?

我现在已经验证了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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值