Как из-за процесса, как правильно получить интерфейс IWebBrowser2 из экземпляра IE? - PullRequest
0 голосов
/ 16 февраля 2011

Я работаю над рамкой автоматизации браузера , которая автоматизирует Internet Explorer, а также другие браузеры.Я сталкиваюсь с неустойчивой проблемой при попытке запустить IE.Фреймворк запускает IE, используя IELaunchURL API, если он присутствует, и использует CreateProcess, если нет.Код для получения интерфейса IWebBrowser2 выглядит следующим образом:

// hwndBrowser is obtained by calling ::EnumWindows() with a function that
// compares the process ID of the window handle to the known process ID of
// the IE instance.
CComPtr<IHTMLDocument2> document;
LRESULT result;
::SendMessageTimeout(hwndBrowser,
                     WM_HTML_GETOBJECT,
                     0L,
                     0L,
                     SMTO_ABORTIFHUNG,
                     1000,
                     (PDWORD_PTR)&result);

// oleacc_instance_handle is obtained from ::LoadLibrary("oleacc.dll")
LPFNOBJECTFROMLRESULT object_pointer =  reinterpret_cast<LPFNOBJECTFROMLRESULT>(
         ::GetProcAddress(oleacc_instance_handle, "ObjectFromLresult"));

if (object_pointer != NULL) {
    HRESULT hr = (*object_pointer)(result,
                                   IID_IHTMLDocument2,
                                   0,
                                   reinterpret_cast<void **>(&document));

    if (SUCCEEDED(hr)) {
        CComPtr<IHTMLWindow2> window;
        hr = document->get_parentWindow(&window);

        if (SUCCEEDED(hr)) {
            // http://support.microsoft.com/kb/257717
            CComQIPtr<IServiceProvider> provider(window);

            if (provider) {
                CComPtr<IServiceProvider> child_provider;
                hr = provider->QueryService(SID_STopLevelBrowser, 
                                            IID_IServiceProvider,
                                            reinterpret_cast<void **>(&child_provider));

                if (SUCCEEDED(hr)) {
                    IWebBrowser2* browser;
                    hr = child_provider->QueryService(SID_SWebBrowserApp,
                                                      IID_IWebBrowser2,
                                                      reinterpret_cast<void **>(&browser));
                    if (SUCCEEDED(hr)) {
                        // The IWebBrowser2 pointer is passed back to the caller.
                        // process_window_info->pBrowser = browser;
                    }
                }
            }
        }
    }
}

Теперь о проблеме: кажется, что мы всегда можем успешно извлечь объект IHTMLDocument2.Однако, когда мы пытаемся вызвать get_parentWindow (), мы иногда получаем результат «класс не зарегистрирован» (0x80040154 REGDB_E_CLASSNOTREG), чаще всего при запуске нового экземпляра IE после закрытия предыдущего.Мы можем получить интерфейс IWebBrowser2, пропустив вызов get_parentWindow () и просто вызвав QueryService непосредственно в документе, но мы получим эту ошибку в дальнейшем, когда попытаемся манипулировать частями документа.Что может вызвать сбой вызова get_parentWindow ()?

Обратите внимание, что весь код можно найти в контексте здесь .

1 Ответ

1 голос
/ 09 марта 2011

Проблема заключалась в использовании потоков в приложении. Мы не ожидали правильного завершения потока перед запуском нового экземпляра IE.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...