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