C ++ проверить, если веб-браузер закрыт - PullRequest
0 голосов
/ 05 июля 2018
#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 (), чтобы проверить, открыт ли веб-браузер, прежде чем просматривать () другую веб-страницу.

Когда я запускаю приложение в первый раз, в диспетчере задач отображаются 2 процесса (iexplorer.exe) & (iexplorer.exe * 32)

Когда я закрываю приложение, иногда процессы закрываются, а иногда нет.

Иногда (iexplorer.exe * 32) закрывается и открывается только (iexplorer.exe). Когда я пытаюсь вызвать init (), в этом случае приложение вылетает.

Использование CodeBlocks 17.12, Windows 2000 и IE 11.

1 Ответ

0 голосов
/ 06 июля 2018

Это прекрасно работает для меня. Может быть, вы звоните www->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 ();
}

И если я закрою браузер (Edge, в моем случае работающий на Windows 10) между вызовами init и browse, я получу:

browse () returned: 800706ba

, что вполне понятно, так как эта ошибка означает «Сервер RPC недоступен». Это конечно не терпит крах.


Редактировать

Глупые ошибки Vista, см. Последние комментарии ОП. После вызова www->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 и доложить?

...