¿Cómo encontrar el puntero IWebBrowser2 para una ventana IE8 con un PID?
-
22-07-2019 - |
Pregunta
hasta ahora, he utilizado con éxito la siguiente función para recuperar el puntero IWebBrowser2 a una instancia de Internet Explorer en ejecución, dado que es 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;
}
Lo que hago es iniciar un proceso explorer.exe
a través de CreateProcess
y luego usar la función anterior para recuperar IWebBrowser2Ptr (para que pueda jugar con el navegador).
Desafortunadamente, esto ya no parece funcionar con Internet Explorer 8, ya que IE8 parece reutilizar procesos, al menos hasta cierto punto. Para dos secuencias de código como:
PROCESS_INFORMATION pi;
// ...
if ( CreateProcess( ..., &pi ) ) {
// Wait a bit to give the browser a change to show its window
// ...
IWebBrowser2 *pWebBrowser = findBrowserByPID( pi.dwProcessId );
}
La primera ejecución de este código funciona bien, la segunda nunca logra recuperar la ventana pWebBrowser.
Después de un poco de depuración, se reveló que la función findBrowserByPID
encuentra muchas ventanas del navegador (y encuentra más después de iniciar una segunda instancia del navegador), pero ninguna de ellas pertenece al nuevo proceso iniciado Parece que todas las ventanas pertenecen al primer proceso de IE que se inició.
¿Alguien sabe una forma alternativa de obtener el puntero IWebBrowser2 a alguna instancia de IE8? ¿O tal vez hay una manera de desactivar esta aparente 'reutilización' de procesos con IE8?
Solución
Si está iniciando el proceso de IE usted mismo, no use CreateProcess; en su lugar, use CoCreateInstance. Eso le devolverá un objeto para el que puede consultar IWebBrowser2, que puede usar a voluntad. La única complejidad es que si la navegación cruza los niveles de integridad (Vista +), el puntero se vuelve inválido. Para solucionar ese problema, sincronice el evento NewProcess, que le permitirá detectar esta condición.
Vea más información aquí: http: / /msdn.microsoft.com/en-us/library/aa752084%28VS.85%29.aspx
Otros consejos
Un par de enfoques alternativos pueden ser:
-
Use una biblioteca como WatiN que podría ayudarlo a hacer lo que sea su objetivo final real si estás intentando automatizar IE.