C ++检查网络浏览器是否关闭
C++ check if web browser closed
#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() 函数来检查 Web 浏览器是否在 browse() 另一个网页之前仍然打开。
当我第一次 运行 应用程序时,任务管理器中显示了 2 个进程 (iexplorer.exe) & (iexplorer.exe *32)
当我关闭应用程序时,进程有时会关闭,有时不会。
有时 (iexplorer.exe *32) 关闭,只有 (iexplorer.exe) 打开。在这种情况下,当我尝试调用 init() 时,应用程序崩溃了。
使用 CodeBlocks 17.12、Windows 2000 和 IE 11。
这对我来说很好用。也许你过早地打电话给 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 ();
}
如果我在调用 init
和 browse
之间关闭浏览器(Edge,在我的例子中,运行 on Windows 10),我得到:
browse () returned: 800706ba
这是完全可以理解的,因为这个错误意味着 "The RPC server unavailable"。它当然不会崩溃。
编辑
愚蠢的 Vista 错误,请参阅 OP 最近的评论。调用 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,然后反馈?
#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() 函数来检查 Web 浏览器是否在 browse() 另一个网页之前仍然打开。
当我第一次 运行 应用程序时,任务管理器中显示了 2 个进程 (iexplorer.exe) & (iexplorer.exe *32)
当我关闭应用程序时,进程有时会关闭,有时不会。
有时 (iexplorer.exe *32) 关闭,只有 (iexplorer.exe) 打开。在这种情况下,当我尝试调用 init() 时,应用程序崩溃了。
使用 CodeBlocks 17.12、Windows 2000 和 IE 11。
这对我来说很好用。也许你过早地打电话给 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 ();
}
如果我在调用 init
和 browse
之间关闭浏览器(Edge,在我的例子中,运行 on Windows 10),我得到:
browse () returned: 800706ba
这是完全可以理解的,因为这个错误意味着 "The RPC server unavailable"。它当然不会崩溃。
编辑
愚蠢的 Vista 错误,请参阅 OP 最近的评论。调用 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,然后反馈?