c++ - 如何从 C++ 程序中检索 DOM 元素?

标签 c++ dom hwnd

我需要从 C++ 程序获取 IE 中显示的网页的所有元素。 我尝试用spy++查看,但只有IEFrame。

所以我正在考虑使用开发工具(IE 中的 F12),我听说有一种方法可以自动化它,是个好主意吗?

谢谢

最佳答案

您可以获得 IHtmlDocument2来自 IE 窗口句柄的引用,甚至是进程外的引用。这在此处记录 https://support.microsoft.com/en-us/help/249232/how-to-get-ihtmldocument2-from-a-hwnd ,但微软并没有真正支持。 然而它看起来今天仍然有效,我已经用 Windows 10 盒子测试了它,而 IE 现在是一个卡住的应用程序,所以不会很快改变。

一旦您获得了 Internet Explorer 的正确 HWND,您就可以使用如下代码获取 DOM。确保 IE 和您的程序运行在相同的安全级别 DOM 与您在进程中(主机、activex 等)编写 IE 时的 DOM 相同,但是出于安全原因,某些功能可能无法正常工作:

void DoSomeDomOperations(HWND hwnd)
{
    UINT msg = RegisterWindowMessage(L"WM_HTML_GETOBJECT");
    LRESULT result = 0;
    SendMessageTimeout(hwnd, msg, NULL, NULL, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&result);
    if (!result)
        return;

    // get main document object
    IHTMLDocument2 *doc = NULL;
    ObjectFromLresult(result, IID_IHTMLDocument2, NULL, (void**)&doc);
    if (!doc)
        return;

    // get document's url
    BSTR url = NULL;
    doc->get_URL(&url);
    wprintf(L"url:%s\n", url);
    SysFreeString(url);

    // get body element
    IHTMLElement *element = NULL;
    doc->get_body(&element);
    if (element)
    {
        BSTR text = NULL;
        element->get_innerText(&text);
        wprintf(L"text:%s\n", text);
        SysFreeString(text);
        element->Release();
    }

    // etc.
    // etc.

    doc->Release();
}

这是一个完整的示例控制台应用程序,可扫描当前运行的所有 IE 进程:

BOOL CALLBACK GetIEServerWindowProc(HWND hwnd, LPARAM lParam)
{
    // enumerate all child windows to find IE's COM server
    wchar_t className[100];
    GetClassName(hwnd, className, 100);
    if (!wcscmp(className, L"Internet Explorer_Server"))
    {
        *((HWND*)lParam) = hwnd;
        return FALSE;
    }
    return TRUE;
}

HWND GetIEServerWindow(HWND hwnd)
{
    HWND serverHwnd = NULL;
    EnumChildWindows(hwnd, GetIEServerWindowProc, (LPARAM)&serverHwnd);
    return serverHwnd;
}

struct IEServer
{
    DWORD processId;
    HWND serverHwnd;
};

BOOL CALLBACK GetIEProcessServerWindowProc(HWND hwnd, LPARAM lParam)
{
    DWORD processId = ((IEServer*)lParam)->processId;
    DWORD pid;
    GetWindowThreadProcessId(hwnd, &pid);
    if (pid == processId)
    {
        HWND serverHwnd = GetIEServerWindow(hwnd);
        if (serverHwnd)
        {
            ((IEServer*)lParam)->serverHwnd = serverHwnd;
            return FALSE;
        }
    }
    return TRUE;
}

HWND GetIEProcessServerWindow(DWORD processId)
{
    IEServer ie = { processId, NULL };
    EnumWindows(GetIEProcessServerWindowProc, (LPARAM)&ie);
    return ie.serverHwnd;
}

void EnumerateIEProcesses()
{
    HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (h == INVALID_HANDLE_VALUE)
        return;

    PROCESSENTRY32 process;
    process.dwSize = sizeof(PROCESSENTRY32);
    if (Process32First(h, &process))
    {
        do
        {
            // we only consider IE processes
            if (!wcscmp(process.szExeFile, L"iexplore.exe"))
            {
                HWND serverHwnd = GetIEProcessServerWindow(process.th32ProcessID);
                if (serverHwnd)
                {
                    DoSomeDomOperations(serverHwnd);
                }
            }
        } while (Process32Next(h, &process));
    }
    CloseHandle(h);
}

int main()
{
    CoInitialize(NULL);

    EnumerateIEProcesses();
    CoUninitialize();
    return 0;
}

关于c++ - 如何从 C++ 程序中检索 DOM 元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45440566/

相关文章:

c++ - 我如何监控文件上的锁以查看它何时被释放? [C++]

android - 可用于 native 模块的库

parsing - DOM 树解析和语法树解析之间的区别?

javascript - Chrome 为自定义 HTML 元素的 offsetWidth 返回 0

java - 如何在 javafx8 中获取节点句柄

c++ - C++ 上的未知错误,错误 : expected primary expression before ';' token

javascript - 遍历(获取)包裹在 <a> 标签内的元素?

winapi - 如何找到MFC使用父进程的主HWND句柄

java - 在 JPanel 中嵌入 HWND(窗口句柄)

c++ - 纠正 C++ 中的异常