Как найти указатель IWebBrowser2 для окна IE8, заданного PID? - PullRequest
2 голосов
/ 05 августа 2009

До сих пор я успешно использовал следующую функцию для получения указателя 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 ]

1 голос
/ 18 сентября 2010

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

  • Получить ссылку через HWND

  • Используйте библиотеку наподобие WatiN , которая может помочь вам сделать то, к чему вы стремитесь, если вы пытаетесь автоматизировать IE.

1 голос
/ 07 августа 2009

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

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

...