[再次尚未修订为清晰起见]如何自动化弹出模态HTML对话框的IE Web应用程序?
我有一个C++程序,它与网站交互。该网站是特定于IE的,我的程序也是如此。
我以普通方式连接到IE的运行实例(超出处理范围 - 请参阅代码)。一旦我得到IWebBrowser2
,我没有问题得到IHTMLDocument2
和与个人IHTMLElement
对象交互,填写字段和单击按钮。
但是,如果网页有JavaScript,调用window.showModalDialog,我卡住了:我需要与弹出窗口中的HTML元素进行交互,就像其他页面一样;但我似乎无法得到其IWebBrowser2
。
弹出总是名为“网页对话框”,并且是包含Internet Explorer_Server
型Internet Explorer_TridentDlgFrame
的一个窗口。但是我无法从我的方式从Internet Explorer_Server
窗口获取IWebBrowser2,这是一个普通的IE实例。
我可以得到IHTMLDocument2Ptr
,但是当我尝试获得IWebBrowser2
时,我得到一个HRESULT
的E_NOINTERFACE
。
的代码是非常标准的东西,如果它是一个“正常”的IE窗口
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
}
}
}
在它的问题的情况下正常工作,这是Vista的和IE8。 (我强调这一点,因为这两个引入了我的代码库中的突破性变化,这在XP/IE7中运行良好。)
再次,我的目标是获得每个IHTMLElement
并与它交互。我无法访问自动化的应用程序的源代码。
我在考虑盲目发送按键到Internet Explorer_Server
窗口,但宁愿不要。
编辑补充:
有人建议让子窗口和发送他们的消息,但我敢肯定,不Internet Explorer_Server
工作;根据Spy ++,没有任何子窗口。 (这不是IE特有的。Java小程序似乎并不有子窗口,无论是。)
更新
在评论中,西蒙毛雷尔说,上面的代码为他工作,而只是为了确保没有错别字,他非常慷慨地在pastebin上发布了一个完整的独立应用程序。当我使用他的代码时,它在同一个地方以相同的方式失败,我意识到他以为我想连接底层页面,而不是弹出窗口。所以我编辑了上面的文字以消除这种模糊性。
什么是例外?调用'pDoc-> QueryInterface'时'pDoc'看起来有效吗? –
@NateHekman:我已经大幅修改了这个问题。 – egrunin
你能确认C++应用程序是否在进程外?什么是“网页对话框”?是脚本调用showModalDialog时弹出的IE窗口? –