从进程外,从IE实例获取IWebBrowser2接口的正确方法是什么?

时间:2011-02-15 22:54:12

标签: c++ internet-explorer com automation

我正在开发browser automation framework,它可以自动化Internet Explorer以及其他浏览器。我试图启动IE时遇到间歇性问题。框架使用IELaunchURL API(如果存在)启动IE,如果不存在则使用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()时,我们有时会收到“class not registered”结果(0x80040154 REGDB_E_CLASSNOTREG),最常见的是在关闭前一个IE后启动IE的新实例。我们可以通过省略对get_parentWindow()的调用并直接在文档上调用QueryService来获取IWebBrowser2接口,但是当我们尝试操作文档的某些部分时,我们将在行下面收到此错误。什么可能导致get_parentWindow()调用失败?

请注意,可以在上下文here中找到整个代码。

1 个答案:

答案 0 :(得分:1)

问题在于在应用程序中使用线程。在启动IE的新实例之前,我们没有正确等待线程终止。