Как найти указатель IWebBrowser2 для окна IE8, заданного PID?

До сих пор я успешно использовал следующую функцию для получения указателя IWebBrowser2 на работающий экземпляр Internet Explorer, учитывая его 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?

2 ответа

Решение

Если вы запускаете процесс IE самостоятельно, не используйте CreateProcess- вместо этого используйте CoCreateInstance. Это вернет вам объект, для которого вы можете запросить IWebBrowser2, который вы можете использовать по желанию. Одна сложность заключается в том, что если навигация пересекает уровни целостности (Vista+), указатель становится недействительным. Чтобы решить эту проблему, синхронизируйте событие NewProcess, которое позволит вам обнаружить это условие.

См. Дополнительную информацию здесь: http://msdn.microsoft.com/en-us/library/aa752084%28VS.85%29.aspx

Пара альтернативных подходов может быть:

Другие вопросы по тегам