【问题标题】:Listen close event of iexplorer in my application在我的应用程序中收听 iexplorer 的关闭事件
【发布时间】:2017-03-24 07:31:32
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: c++ windows setwindowshookex


    【解决方案1】:

    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 控件”(SHDocVw.dll) 和“Microsoft HTML 对象库”(mshtml.dll) 的引用添加到项目中。它们是 COM 对象,应该在您的“C:\Windows\System32”目录中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多