Como encontrar o ponteiro IWebBrowser2 para uma janela do IE8 dado um PID?
-
22-07-2019 - |
Pergunta
até agora, eu usei com sucesso a seguinte função para recuperar o ponteiro IWebBrowser2 para uma instância do Internet Explorer em execução, dado que é 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;
}
O que eu faço é lançar um processo explorer.exe
via CreateProcess
e, em seguida, usar a função acima para recuperar o IWebBrowser2Ptr a ele (para que eu possa mexer com o navegador).
Infelizmente, isso não parece funcionar com o Internet Explorer 8 mais, desde IE8 parece processos de reutilização - pelo menos em algum grau. Por duas seqüências 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 );
}
A primeira execução deste código funciona bem, o segundo nunca consegue recuperar a janela de pWebBrowser.
Depois de um pouco de depuração, foi revelado que a função findBrowserByPID
faz encontrar muitas janelas do navegador (e ele encontrar mais depois de iniciar uma segunda instância do navegador), mas nenhum deles pertencem ao processo recém-iniciado. Parece que todas as janelas pertencem ao primeiro processo de IE que foi iniciado.
Alguém sabe uma maneira alternativa de obter o ponteiro IWebBrowser2 para alguma instância IE8? Ou há talvez uma maneira de desativar esse 'reutilização' aparente de processos com IE8?
Solução
Se você está lançando o IE processo de si mesmo, não use CreateProcess-- em vez disso, o uso CoCreateInstance. Isso irá retornar um objeto para o qual você pode consultar para IWebBrowser2, que você pode usar à vontade. A única complexidade é que se a navegação atravessa níveis de integridade (Vista +) o ponteiro torna-se inválido. Para resolver esse problema, sincronize o evento NewProcess, o que lhe permitirá detectar essa condição.
Veja mais algumas informações aqui: http: / /msdn.microsoft.com/en-us/library/aa752084%28VS.85%29.aspx
Outras dicas
Um par de abordagens alternativas podem ser:
-
Use uma biblioteca como WatiN que pode ajudá-lo a fazer o seu objetivo final real é se você está tentando automatizar IE.