在我的应用程序中监听iexplorer的关闭事件

时间:2017-03-24 07:31:33

标签: c++ windows setwindowshookex

我正在用C ++编写一个win32应用程序,我希望它能在所有iexplorer.exe关闭时执行某些操作。

我知道SetWindowsHook()在我的情况下可能很有用。

但是如果我不知道IE的进程或线程ID,因为每次打开IE都会获得不同的线程ID。

如果我不使用计时器检查进程列表以获取iexplorer的ID,是否还有另一种方法可以在我的win32应用程序中监听IE的关闭事件?

1 个答案:

答案 0 :(得分:0)

IE的对象称为InternetExplorerShellWindows object是InternetExplorer对象的集合。但这里变得复杂了。并非所有InternetExplorer对象都是您所谓的IE窗口。其中一些是“Windows资源管理器”窗口。请参阅About the Browser (Internet Explorer)

以下是托管C ++控制台程序,它列出了现有窗口并设置了现有窗口数的计数。然后它使用WindowRegistered和WindowRevoked事件来监视窗口的创建和关闭。那些事件没有很好地记录在案。下面的示例使用每个InternetExplorer对象的Document成员来确定窗口是否具有HTML。但请参阅c# - Distinguishing IE windows from other windows when using SHDocVw中的评论; IE窗口可能没有HTML。

请注意,以下示例使用AutoResetEvent来保持程序运行,因为它是一个控制台程序。

以下是标题:

#pragma once

#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <ShlObj.h>
#include <comdef.h>
#include <vcclr.h>

以下是该计划:

#include "stdafx.h"
using namespace System;
using namespace System::Threading;

static int Browsers = 0;
static gcroot<AutoResetEvent^> Event;

bool IsBrowser(SHDocVw::InternetExplorer ^ ie)
{
    MSHTML::IHTMLDocument2^ Document;
    try { Document = (MSHTML::IHTMLDocument2^)ie->Document; }
    catch (Exception^ ex)
    {
        return false;
    }
    return Document != nullptr;
}

 static void WindowRegistered(int lCookie) {
    ++Browsers;
    Console::WriteLine("WindowRegistered");
}

static void WindowRevoked(int lCookie) {
    --Browsers;
    Console::WriteLine("WindowRevoked");
    if (Browsers <= 0)
        Event->Set();
}

int main(array<System::String ^> ^args)
{
    SHDocVw::ShellWindows^ swList = gcnew SHDocVw::ShellWindowsClass();
    Console::WriteLine(L"{0} instances", swList->Count);
    for each (SHDocVw::InternetExplorer ^ ie in swList) {
        Console::WriteLine(ie->LocationURL);
        if (IsBrowser(ie)) {
            Console::WriteLine("HTML document");
            ++Browsers;
        }
        else
            Console::WriteLine("Not HTML");
        }
    if (Browsers == 0)
    {
        Console::WriteLine("No browsers");
        return 0;
    }
    Event = gcnew AutoResetEvent(false);
    swList->WindowRegistered += gcnew SHDocVw::DShellWindowsEvents_WindowRegisteredEventHandler(WindowRegistered);
    swList->WindowRevoked += gcnew SHDocVw::DShellWindowsEvents_WindowRevokedEventHandler(WindowRevoked);
    Event->WaitOne();
    Console::WriteLine("No more browsers");
    return 0;
}

现在我意识到这种方式存在问题。即使窗口不是IE窗口,WindowRegistered和WindowRevoked处理程序也会递增浏览器计数。我不知道如何确定cookie传递给WindowRegistered和WindowRevoked表示的窗口。几年前,我花了几天或更多的时间来试图解决这个问题。所以你应该做的是以某种方式在每个WindowRegistered和WindowRevoked事件之后重新列出所有窗口。

您需要将“Microsoft Internet Controls”(SHDocVw.dll)和“Microsoft HTML Object Library”(mshtml.dll)的引用添加到项目中。它们是COM对象,应位于“C:\ Windows \ System32”目录中。