Comment trouver le pointeur IWebBrowser2 pour une fenêtre IE8 à partir d'un PID?
-
22-07-2019 - |
Question
jusqu'à présent, j'ai utilisé avec succès la fonction suivante pour récupérer le pointeur IWebBrowser2 sur une instance Internet Explorer en cours d'exécution, étant donné qu'il s'agit d'un 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;
}
Ce que je fais est de lancer un processus explorer.exe
via CreateProcess
, puis d'utiliser la fonction ci-dessus pour récupérer le IWebBrowser2Ptr (afin que je puisse manipuler le navigateur).
Malheureusement, cela ne semble plus fonctionner avec Internet Explorer 8, car IE8 semble réutiliser des processus, du moins dans une certaine mesure. Pour deux séquences de code telles que:
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 première exécution de ce code fonctionne correctement, la seconde ne parvient jamais à récupérer la fenêtre pWebBrowser.
Après un peu de débogage, il a été révélé que la fonction findBrowserByPID
trouve beaucoup de fenêtres de navigateur (et en trouve plus après le démarrage d'une deuxième instance de navigateur), mais aucune d'entre elles n'appartient à la nouvelle. processus commencé. Il semble que toutes les fenêtres appartiennent au premier processus IE qui a été lancé.
Quelqu'un connaît-il un autre moyen d'obtenir le pointeur IWebBrowser2 sur une instance IE8? Ou est-il possible de désactiver cette "réutilisation" apparente des processus avec IE8?
La solution
Si vous lancez vous-même le processus IE, n'utilisez pas CreateProcess, utilisez plutôt CoCreateInstance. Cela vous retournera un objet pour lequel vous pouvez interroger IWebBrowser2, que vous pouvez utiliser à volonté. La complexité est que si la navigation dépasse les niveaux d'intégrité (Vista +), le pointeur devient invalide. Pour résoudre ce problème, synchronisez l'événement NewProcess, ce qui vous permettra de détecter cette condition.
Plus d'informations ici: http: / /msdn.microsoft.com/en-us/library/aa752084%28VS.85%29.aspx
Autres conseils
Quelques approches alternatives pourraient être:
-
Utilisez une bibliothèque telle que WatiN qui pourrait vous aider à atteindre votre objectif final si vous essayez d'automatiser IE.