c++ - 从进程外,从 IE 实例获取 IWebBrowser2 接口(interface)的正确方法是什么?

标签 c++ internet-explorer com automation

我正在研究 browser automation framework ,它使 Internet Explorer 和其他浏览器自动化。我在尝试启动 IE 时遇到间歇性问题。如果存在,框架使用 IELaunchURL API 启动 IE,如果不存在,则使用 CreateProcess。获取IWebBrowser2接口(interface)的代码如下:

// 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 实例后启动一个新的 IE 实例。我们可以通过省略对 get_parentWindow() 的调用并直接在文档上调用 QueryService 来获取 IWebBrowser2 接口(interface),但是当我们尝试操作文档的某些部分时,我们将进一步收到此错误。什么会导致 get_parentWindow() 调用失败?

请注意,完整的代码可以在上下文中找到 here .

最佳答案

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

关于c++ - 从进程外,从 IE 实例获取 IWebBrowser2 接口(interface)的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5010502/

相关文章:

python - Python C API 的常量正确性

c++ - 如何将 BYTE 数组转换为 char 数组以使用套接字 c++ 发送

c++ - 理解托管 C++

javascript - 在 IE 中输入字段不显示光标或无法输入字母

javascript - 如果满足 <noscript> OR &lt;!--[if lte IE 7]> 条件注释,则显示内容,而不复制内容?

c# - 使用 c# 运行带有 activex 对象的 dll

.net - 是否有支持 dotnet 或 com 互操作的 lisp 实现或第 3 方库

c# - 从未通过 C# 注册的 C++ COM 服务器访问 COM 接口(interface)

c++ - 通过右值引用返回 lambda?

javascript - IE8 : element:first-child deosn't work (selects parent of what I actually want)