2017-08-01 65 views
1

我需要从C++程序中获取IE中显示的所有网页元素。 我试图用间谍++看,但只有IEFrame。如何从C++程序中检索DOM元素?

所以我想使用开发工具(在IE中F12),我听说有一种方法来自动它,一个好主意?

感谢

回答

2

你可以从IE的窗口句柄的IHtmlDocument2参考,甚至退出的进程。这里记录在这里https://support.microsoft.com/en-us/help/249232/how-to-get-ihtmldocument2-from-a-hwnd,但并不真正支持微软。但是它看起来像今天仍然有效,我已经用Windows 10盒子测试过它,而IE现在是一个冷冻应用程序,所以不会很快改变。

一旦你有适当的Internet Explorer的HWND,比你可以用这样的代码得到DOM。确保IE和您的程序在相同的安全级别运行 DOM与编写IE进程(主机,activex等)时相同,但出于安全原因,某些事情可能不起作用:

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; 
} 
+0

感谢您简单等完整的解决方案,它完美的作品! – Entretoize