如何在给定 PID 的情况下找到 IE8 窗口的 IWebBrowser2 指针?
-
22-07-2019 - |
题
到目前为止,我已成功使用以下函数来检索指向正在运行的 Internet Explorer 实例的 IWebBrowser2 指针(给定其 PID)。
static SHDocVw::IWebBrowser2Ptr findBrowserByPID( DWORD pid )
{
SHDocVw::IShellWindowsPtr ptr;
ptr.CreateInstance(__uuidof(SHDocVw::ShellWindows));
if ( ptr == NULL ) {
return 0;
}
// number of shell windows
const long nCount = ptr->GetCount();
// iterate over all shell windows
for (long i = 0; i < nCount; ++i) {
// get interface to item no i
_variant_t va(i, VT_I4);
IDispatchPtr spDisp = ptr->Item(va);
SHDocVw::IWebBrowser2Ptr spBrowser(spDisp);
if (spBrowser != NULL) {
// if there's a document we know this is an IE object
// rather than a Windows Explorer instance
HWND browserWindow;
try {
browserWindow = (HWND)spBrowser->GetHWND();
} catch ( const _com_error &e ) {
// in case ->GetHWND() fails
continue;
}
DWORD browserPID;
GetWindowThreadProcessId( browserWindow, &browserPID );
if ( browserPID == pid ) {
return spBrowser;
}
}
}
return 0;
}
我所做的是启动一个 explorer.exe
处理通过 CreateProcess
然后使用上面的函数检索 IWebBrowser2Ptr (这样我就可以摆弄浏览器)。
不幸的是,这似乎不再适用于 Internet Explorer 8,因为 IE8 似乎重用了进程——至少在某种程度上是这样。对于两个代码序列,例如:
PROCESS_INFORMATION pi;
// ...
if ( CreateProcess( ..., &pi ) ) {
// Wait a bit to give the browser a change to show its window
// ...
IWebBrowser2 *pWebBrowser = findBrowserByPID( pi.dwProcessId );
}
第一次运行此代码工作正常,第二次运行则无法检索 pWebBrowser 窗口。
经过一番调试后发现 findBrowserByPID
函数确实找到了很多浏览器窗口(并且在启动第二个浏览器实例后发现了更多),但它们都不属于新启动的进程。看来所有的窗口都属于第一个启动的IE进程。
有谁知道获取 IWebBrowser2 指针到某个 IE8 实例的替代方法吗?或者是否有一种方法可以禁用 IE8 中这种明显的进程“重用”?
解决方案
如果你自己启动IE进程,不要使用CreateProcess--而是使用CoCreateInstance的。这将返回一个对象,你可以查询IWebBrowser2的,你可以随意使用。在一个复杂的是,如果导航跨越完整性级别(Vista的+)指针变为无效。为了解决这一问题,同步的NewProcess事件,这将允许您检测到这种情况。
在这里看到更多的信息: HTTP:/ /msdn.microsoft.com/en-us/library/aa752084%28VS.85%29.aspx
其他提示
几种替代方法可能是:
使用类似的库 等待 如果您想实现 IE 自动化,这可能会帮助您实现真正的最终目标。