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

Listen close event of iexplorer in my application

我正在用 C++ 编写一个 win32 应用程序,我希望它在所有 iexplorer.exe 关闭时做一些事情。

我知道 SetWindowsHook() 可能对我有用。

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

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

IE 的 object 称为 InternetExplorer. TheShellWindows object is a collection of InternetExplorer objects. But here it gets complicated. Not all InternetExplorer objects are what you would call an IE window. Some of them are "Windows Explorer" windows. See About the Browser (Internet Explorer)

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

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

以下是header:

#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;
}

现在我才意识到这种工作方式存在问题。即使 window 不是 IE window,WindowRegistered 和 WindowRevoked 处理程序也会增加浏览器计数。我不知道如何确定传递给 WindowRegistered 和 WindowRevoked 的 cookie 代表什么 window。几年前,我花了几天或更多的时间试图弄清楚这个问题。所以你应该做的是在每个 WindowRegistered 和 WindowRevoked 事件之后以某种方式 re-list 所有 windows。

您需要将 "Microsoft Internet Controls" (SHDocVw.dll) 和 "Microsoft HTML Object Library" (mshtml.dll) 的引用添加到项目中。它们是 COM object,应该在您的 "C:\Windows\System32" 目录中。