अब मैं सत्यापित eval
दृष्टिकोण IE9, IE10 और IE11 के साथ लगातार काम करता है (त्रुटि जाँच breavity के लिए छोड़ दिया) है
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
से भी बेहतर Feels, क्योंकि यह वास्तव में result
देता है। यह WebBrowser
WinForms के साथ सी # में भी काम करता है:
var result = webBrowser1.Document.InvokeScript("eval", new object[] { "confirm('see this?')" });
MessageBox.Show(result.ToString());
जिसके अनुसार, execScript
अभी भी IE11 पूर्वावलोकन के लिए काम करता है:
CComVariant result;
m_htmlWindow->execScript(CComBSTR(L"confirm('See this too?')"), CComBSTR(L"JavaScript"), &result);
result.ChangeType(VT_BSTR);
MessageBoxW(V_BSTR(&result));
और यह अभी भी result
को छोड़ देता है, के रूप में यह हमेशा किया है।
थोड़ा सा विषय, लेकिन इसके लिए आपको eval
से चिपकने की आवश्यकता नहीं है। यह दृष्टिकोण लोड किए गए पृष्ठ (IDispatch इंटरफ़ेस के माध्यम से) के window
ऑब्जेक्ट के नामस्थान के अंदर उपलब्ध किसी नामित विधि को निष्पादित करने की अनुमति देता है। आप अपनी खुद की समारोह कॉल कर सकते हैं और नहीं बल्कि एक स्ट्रिंग पैरामीटर की तुलना में यह में एक जीवित 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
के लिए ऊपर प्रत्यक्ष कॉल पसंद करेंगे।
[संपादित]
यह बाहर के प्रक्रिया कॉल के लिए इस दृष्टिकोण काम करने के लिए कुछ तोड़ मरोड़ लेता है। @JimEvans ने टिप्पणियों में बताया, Invoke
त्रुटि 0x80020006 ("अज्ञात नाम") लौटा रहा था। हालांकि, test HTA app ने ठीक काम किया, मुझे नाम संकल्प के लिए IDispatchEx::GetDispId को आजमाने का क्या लगा। यही कारण है कि वास्तव में काम किया (त्रुटि जाँच को छोड़ दिया):
CComDispatchDriver dispWindow;
htmlWindow->QueryInterface(&dispWindow);
CComPtr<IDispatchEx> 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
पूर्ण सी ++ परीक्षण ऐप आ गया है: http://pastebin.com/ccZr0cG2
[अद्यतन]
यह अद्यतन एक बच्चे की एक window
वस्तु पर __execScript
विधि बनाता है iframe
, बाहर की proc।इंजेक्शन वाले कोड को window
ऑब्जेक्ट को बाद में उपयोग के लिए लक्ष्य को वापस करने के लिए अनुकूलित किया गया था (iframe
ऑब्जेक्ट प्राप्त करने के लिए आउट ऑफ़ ऑफ प्रो कॉल की श्रृंखला बनाने की आवश्यकता नहीं है, यह मुख्य विंडो के संदर्भ में किया जाता है):
CComBSTR __execScriptCode(L"(window.__execScript = function(exp) { return eval(exp); }, window.self)");
नीचे C++ कंसोल ऐप (pastebin) के लिए कोड है, कुछ त्रुटि जांच ब्रेवटी के लिए छोड़ दी गई है। एक संबंधित prototype in .HTA भी है, जो अधिक पठनीय है।
//
// http://stackoverflow.com/questions/18342200/how-do-i-call-eval-in-ie-from-c/18349546//
//
#include <tchar.h>
#include <ExDisp.h>
#include <mshtml.h>
#include <dispex.h>
#include <atlbase.h>
#include <atlcomcli.h>
#define _S(a) \
{ HRESULT hr = (a); if (FAILED(hr)) return hr; }
#define disp_cast(disp) \
((CComDispatchDriver&)(void(static_cast<IDispatch*>(disp)), reinterpret_cast<CComDispatchDriver&>(disp)))
struct ComInit {
ComInit() { ::CoInitialize(NULL); }
~ComInit() { CoUninitialize(); }
};
int _tmain(int argc, _TCHAR* argv[])
{
ComInit comInit;
CComPtr<IWebBrowser2> 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<IDispatch> dispDoc;
_S(ie->get_Document(&dispDoc));
CComPtr<IHTMLDocument2> htmlDoc;
_S(dispDoc->QueryInterface(&htmlDoc));
CComPtr<IHTMLWindow2> htmlWindow;
_S(htmlDoc->get_parentWindow(&htmlWindow));
CComPtr<IDispatchEx> 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<IDispatchEx> 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;
}
मेरा अनुमान है कि आप इसे पसंद आप जावास्क्रिप्ट में होगा करना चाहते हैं, पेज के डोम के लिए एक नई स्क्रिप्ट तत्व जोड़कर है, लेकिन मैं IE देव टीम के साथ की जाँच कर रहा हूँ ... – EricLaw
@JimEvans , मेरे पास IE11 को स्थापित करने के लिए इंस्टॉल नहीं किया गया है, लेकिन 'eval' का उपयोग करके IE10 के लिए निम्न कार्य करता है: 'CComDispatchDriver window = m_window;/* IHTMLWindow2 */ विंडो। इन्वोक 1 (एल "eval", और CComVariant (एल "चेतावनी (सच)"); ' – Noseratio