[noch einmal überarbeitet für Klarheit]Wie automatisiere ich eine IE-Webanwendung, die einen modalen HTML-Dialog öffnet?
Ich habe ein C++ Programm, das mit einer Website interagiert. Die Seite ist IE-spezifisch und mein Programm auch.
Ich verbinde die laufende Instanz von IE auf eine gewöhnliche Weise (aus Prozess - siehe Code). Sobald ich die IWebBrowser2
bekomme, habe ich kein Problem, die IHTMLDocument2
und Interaktion mit den einzelnen IHTMLElement
Objekte, Felder ausfüllen und klicken Sie auf Schaltflächen.
Aber wenn die Webseite Javascript hat, die window.showModalDialog aufruft, stecke ich fest: Ich muss mit den HTML-Elementen im Popup interagieren, genau wie die anderen Seiten; aber ich kann nicht seine IWebBrowser2
bekommen.
Das Popup ist immer "Webseitendialog" und ist ein Fenster vom Typ Internet Explorer_TridentDlgFrame
mit einem Internet Explorer_Server
. Aber ich kann nicht den IWebBrowser2 aus dem Internet Explorer_Server
Fenster so wie ich kann, wenn es eine normale IE-Instanz ist.
Ich kann die IHTMLDocument2Ptr
bekommen, aber wenn ich versuche, die IWebBrowser2
ich eine HRESULT
von E_NOINTERFACE
bekommen zu bekommen.
Der Code ziemlicher Standard ist und funktioniert gut, wenn es sich um eine 'normale' IE-Fenster ist
IHTMLDocument2Ptr pDoc;
LRESULT lRes;
/* hWndChild is an instance of class "Internet Explorer_Server" */
UINT nMsg = ::RegisterWindowMessage("WM_HTML_GETOBJECT");
::SendMessageTimeout(hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000,
(DWORD*)&lRes);
LPFNOBJECTFROMLRESULT pfObjectFromLresult =
(LPFNOBJECTFROMLRESULT)::GetProcAddress(hInst, "ObjectFromLresult");
if (pfObjectFromLresult != NULL)
{
HRESULT hr;
hr = (*pfObjectFromLresult)(lRes, IID_IHTMLDocument, 0, (void**)&pDoc);
if (SUCCEEDED(hr)) {
IServiceProvider *pService;
hr = pDoc->QueryInterface(IID_IServiceProvider, (void **) &pService);
if (SUCCEEDED(hr))
{
hr = pService->QueryService(SID_SWebBrowserApp,
IID_IWebBrowser2, (void **) &pBrowser);
// This is where the problem occurs:
// hr == E_NOINTERFACE
}
}
}
Falls es darauf ankommt, ist dies Vista und IE8. (Ich betone dies, weil beide diese brechenden Änderungen in meiner Codebasis einführten, die mit XP/IE7 gut gearbeitet hatten.)
Noch einmal, mein Ziel ist, jedes IHTMLElement
10 zu bekommen und mit ihm zu interagieren. Ich habe keinen Zugriff auf den Quellcode der Anwendung, die ich automatisiere.
Ich überlege, senden Tastenanschläge blind zu dem Internet Explorer_Server
Fenster, würde aber eher nicht.
Edited hinzufügen:
Jemand schlug vor, die Kind-Fenster bekommen und ihnen Nachrichten senden, aber ich bin mir ziemlich sicher, dass nicht mit Internet Explorer_Server
funktioniert; Laut Spy ++ gibt es keine untergeordneten Fenster. (Dies ist nicht IE-spezifisch. Java-Applets scheinen nicht untergeordnete Fenster zu haben, auch nicht.)
aktualisieren
In den Kommentaren, sagte Simon Maurer der obige Code für ihn gearbeitet, und nur zu Stellen Sie sicher, dass es keine Tippfehler gab. Er hat sehr großzügig eine vollständige Standalone-App auf pastebin veröffentlicht. Als ich seinen Code benutzte, scheiterte er auf die gleiche Weise an der gleichen Stelle, und mir wurde klar, dass er dachte, ich wollte mich mit der zugrunde liegenden Seite verbinden, nicht mit dem Popup. Also habe ich den obigen Text bearbeitet, um diese Mehrdeutigkeit zu beseitigen.
Was ist die Ausnahme? Erscheint 'pDoc' beim Aufruf von' pDoc-> QueryInterface'? –
@NateHekman: Ich habe die Frage wesentlich überarbeitet. – egrunin
Können Sie bestätigen, dass die C++ App nicht in Bearbeitung ist? Was ist ein "Webseiten-Dialog"? Ist es das IE-Fenster, das erscheint, wenn ein Skript showModalDialog aufruft? –