【发布时间】:2013-04-10 00:02:09
【问题描述】:
[再次修订为清楚起见]
我有一个与网站交互的 C++ 程序。该网站是特定于 IE 的,我的程序也是如此。
我正在以普通方式连接到正在运行的 IE 实例(进程外——参见代码)。获得IWebBrowser2 后,我就可以轻松获得IHTMLDocument2 并与各个IHTMLElement 对象交互、填写字段并单击按钮。
但如果网页有调用window.showModalDialog 的javascript,我就会陷入困境:我需要与弹出窗口中的HTML 元素进行交互,就像其他页面一样;但我似乎无法得到它的IWebBrowser2。
弹出窗口总是标题为“网页对话框”,是一个Internet Explorer_TridentDlgFrame 类型的窗口,其中包含Internet Explorer_Server。但是我无法像普通 IE 实例那样从Internet Explorer_Server 窗口获取 IWebBrowser2。
我可以得到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 小程序似乎也没有子窗口。)
更新
在 cmets 中,Simon Maurer 说上面的代码对他有用,为了确保没有错别字,他非常慷慨地在 pastebin 上发布了一个完整的独立应用程序。当我使用他的代码时,它在同一个地方以同样的方式失败,我意识到他认为我想连接到底层页面,而不是弹出窗口。所以我编辑了上面的文字以消除这种歧义。
【问题讨论】:
-
有什么例外?当您调用
pDoc->QueryInterface时,pDoc看起来有效吗? -
@NateHekman:我已经大幅修改了这个问题。
-
你能确认 c++ 应用程序是进程外的吗?什么是“网页对话框”?是不是脚本调用showModalDialog时弹出的IE窗口?
-
@SimonMourier - 我已经修改了这个问题。 是的,它肯定是在进程之外。 (该应用程序的早期版本在进程中工作,但在 IE8 上停止工作。)是,我假设该应用程序正在调用 showModalDialog。
-
仅供参考,我已经在 Windows 8 上使用 IE 10 测试了这段代码,它可以工作,即使显示了模式对话框。
标签: c++ internet-explorer browser-automation iwebbrowser2