【问题标题】:C++ check if web browser closedC ++检查Web浏览器是否关闭
【发布时间】:2018-07-05 13:29:15
【问题描述】:
#include <windows.h>
#include <exdisp.h>

class CWebBrowser{

    public:
        HRESULT hr;
        IWebBrowserApp *www;

    HRESULT init(){
        CLSID clsid;
        const IID IID_IEApplication = {0x0002DF05,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};

        if(www) hr = www->put_Visible(-1);
        if(hr!=0 || www==NULL){
            QuitBrowser();
            hr=CLSIDFromProgID(L"InternetExplorer.Application",&clsid);
            if(hr==0) hr=CoCreateInstance(clsid,NULL,CLSCTX_ALL,IID_IEApplication,reinterpret_cast<void**>(&www));
            if(hr==0) hr = www->put_Visible(-1);
        }
    return hr;
   }

    HRESULT browse(BSTR addr){
        VARIANT vEmpty;
        VariantInit(&vEmpty);

        hr=www->Navigate(addr, &vEmpty, &vEmpty, &vEmpty, &vEmpty);
        VariantClear(&vEmpty);

    return hr;
    }

    void QuitBrowser(){
        if(www){
            www->Quit();
            www->Release();
            www=NULL;
        }
    }

    CWebBrowser(){
        hr=CoInitialize(NULL);
    }

    ~CWebBrowser(){
        if(www){
            www->Quit();
            www->Release();
            www=NULL;
        }
        CoUninitialize();
    }
};

我正在调用 init() 函数来检查浏览器是否仍然打开,然后再browse() 另一个网页。

当我第一次运行应用程序时,任务管理器 (iexplorer.exe) 和 (iexplorer.exe *32) 中显示 2 个进程

当我关闭应用程序时,有时进程会关闭,有时不会。

有时 (iexplorer.exe *32) 会关闭,而只有 (iexplorer.exe) 会打开。在这种情况下,当我尝试调用 init() 时,应用程序崩溃了。

使用 CodeBlocks 17.12、Windows 2000 和 IE 11。

【问题讨论】:

  • 可能在每次浏览之前都进行初始化会有帮助吗?
  • 创建一个新实例。我将无法执行诸如登录网站之类的操作,因为会话将无效。
  • 是的,但 AFAIK 之前您可以使用 GetActiveObject 检查/获取正在运行的应用程序实例。如果失败,则根据需要调用 CoCreateInstance

标签: c++ winapi exception codeblocks


【解决方案1】:

这对我来说很好。也许你过早地打电话给www-&gt;Release()

这是我的MCVE

#include <Windows.h>
#include <assert.h>
#include <Exdisp.h>
#include <iostream>

#pragma comment (lib, "SHDOCVW.lib")

IWebBrowserApp *www;

HRESULT init()
{
    CLSID clsid;
    const IID IID_IEApplication = {0x0002DF05,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
    HRESULT hr = CLSIDFromProgID (L"InternetExplorer.Application", &clsid);

    if (hr)
    {
        std::cout << std::hex << "CLSIDFromProgID failed, error " << hr << "\n";
        return hr;
    }

    hr = CoCreateInstance (clsid, NULL, CLSCTX_ALL, IID_IEApplication, reinterpret_cast<void**>(&www));
    if (hr)
    {
        std::cout << std::hex << "CoCreateInstance failed, error " << hr << "\n";
        return hr;
    }

    hr = www->put_Visible(-1);
    if (hr)
    {
        std::cout << std::hex << "put_Visible failed, error " << hr << "\n";
        www->Release ();
        www = nullptr;
        return hr;
    }

    return S_OK;
}

HRESULT browse(BSTR addr)
{
    HRESULT hr;

    if (www)
    {
        VARIANT vEmpty;
        VariantInit (&vEmpty);
        hr = www->Navigate (addr, &vEmpty, &vEmpty, &vEmpty, &vEmpty);
        VariantClear (&vEmpty);
    }

    return hr;
}

int main ()
{
    HRESULT hr = CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
    assert (hr == 0);
    int mb_result;

    while (1)
    {
        hr = init ();

        if (hr == 0)
        {
            mb_result = MessageBoxW (NULL, L"About to browse", L"Browser Test", MB_OKCANCEL);
            if (mb_result == IDOK)
            {
                BSTR url = SysAllocString (L"https://www.google.com");
                hr = browse (url);
                SysFreeString (url);
                if (hr)
                    std::cout << "browse () returned: " << std::hex << hr << "\n";
            }

            mb_result = MessageBoxW (NULL, L"About to quit", L"Browser Test", MB_OKCANCEL);
            if (mb_result == IDOK)
                www->Quit ();
            www->Release ();
            www = nullptr;
        }

        mb_result = MessageBoxW (NULL, L"Again?", L"Browser Test", MB_YESNO);
        if (mb_result == IDNO)
            break;
    }

    CoUninitialize ();
}

如果我在调用 initbrowse 之间关闭浏览器(在我的情况下是在 Windows 10 上运行的 Edge),我会得到:

browse () returned: 800706ba

这是完全可以理解的,因为这个错误意味着“RPC 服务器不可用”。它当然不会崩溃。


编辑

愚蠢的 Vista 错误,请参阅 OP 最近的 cmets。在调用 www-&gt;Quit() 之后,如果您至少对它太快,对 CoCreateInstance() 的下一次调用将失败。

所以,有两个建议。

1(可能有效):

for (int i = 0; i < 10; ++i)
{
    hr = CoCreateInstance (clsid, NULL, CLSCTX_ALL, IID_IEApplication, reinterpret_cast<void**>(&www));
    if (hr != ERROR_SHUTDOWN_IS_SCHEDULED)    // not really
        break;
    Sleep (1000);
}

2(更激烈一点,为简洁起见省略了错误处理):

// www->Quit ();
HWND hWnd;
hr = www->get_HWND ((SHANDLE_PTR *) &hWnd);
if (hr == S_OK)
{
    DWORD processID;
    if (GetWindowThreadProcessId (hWnd, &processID))
    {
        HANDLE hProcess = OpenProcess (PROCESS_TERMINATE, FALSE, processID);
        if (hProcess)
        {
            TerminateProcess (hProcess, (DWORD) -1);
            CloseHandle (hProcess);
        }
     }
}

想试一试,OP,然后报告?

【讨论】:

  • 感谢您给我一些指导。应用程序崩溃的频率降低了。似乎 iexplorer.exe 需要一些时间才能关闭,有时甚至永远不会关闭。那是我的应用程序崩溃的时候。我实际上已经创建了一个 CWebBrowser 类。我已经更新了我的帖子。有什么想法吗?
  • 感谢更新,我会试验的。 Windows 2000 - 你真的是那个意思吗?只是为了确认,IE11,而不是 Edge。
  • 我已经更新了我的测试程序,如上所示,它工作正常。我无法在我的平台上使用 IE11 进行测试。您的 init 函数中存在一个明显的问题(对我来说,这似乎过于复杂)可能会也可能不会给您带来麻烦。我建议你做的是运行 my 测试程序,看看它是否可以在你的机器上运行。如果是这样,您知道从哪里开始查看您自己的代码中的错误。如果没有,请告诉我你有什么新信息,我会看看我能做什么(可能不会很多)。
  • 特别是,我需要知道您实际运行的是哪个版本的 Windows(当然不可能是 W2K)。谢谢。
  • 感谢您与我一起解决这个问题。多次尝试您的代码时出现以下错误。 browse() 返回:0 browse() 返回:0 断言失败:hr == 0,文件 H:\C\Test2\main.cpp,第 49 行 此应用程序已请求运行时以不寻常的方式终止它。请联系应用程序的支持团队以获取更多信息。抱歉,Windows 版本是 server 2018
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-29
  • 2012-09-18
  • 2012-07-25
  • 1970-01-01
相关资源
最近更新 更多