【问题标题】:Get active Tab URL in Chrome with C++使用 C++ 在 Chrome 中获取活动标签 URL
【发布时间】:2018-01-29 15:07:19
【问题描述】:

several answered questions about this on stackoverflow,但它们似乎已经过时并且不再工作了。 Chrome 有changed its structure entirely。如果我尝试AccessibleObjectFromEvent 技术,那么我只会得到accName 和accValue 的NULL 值。似乎 there are solutions for python,但是我找不到 C++ 的任何解决方案。如何在 C++ 中检索活动的 Tab URL?

【问题讨论】:

  • 我确定这是一个骗子。再搜索一下。
  • 你试过调试代码吗?检查get_accValue()get_accName() 的返回值应该会提供一些线索。
  • @DavidHeffernan 我再次查看了大多数最新(约 1 岁)的 c++ 问题,但找不到解决方案,只有旧的不再适用。
  • @zett42 如前所述,两者都返回 NULL。
  • 这还是个骗子。如果你能从 Python 中看到如何使用 UIAutomation 来实现,那么你可以直接翻译成 C++。或者您是否需要其他人为您完成这项工作。

标签: c++ google-chrome winapi


【解决方案1】:

我们需要UI Automation

使用Window SDK中的Inspect工具,我们可以得到Chrome地址栏的属性名:

Name:           "Address and search bar"
ControlType:    UIA_EditControlTypeId

我们将寻找UIA_EditControlTypeId,因为它与语言无关。

但是 html 文档中可以有另一个编辑框,它可能会显示在主工具栏之前。因此,我们需要跳过 html 文档,找到包含地址栏的“窗格”。此窗格称为“Google Chrome”,应该只有其中一个。地址栏是这个独特的“Google Chrome 窗格”的子项。

如果浏览器处于全屏模式,则没有地址栏。我们需要一种备份方法来查找地址。例如,您可以在文档中查找它。但该文档也可能不可用,例如当 Chrome 已最小化时。

以下示例使用 ATL COM 类,它需要 Visual Studio

#define UNICODE
#include <Windows.h>
#include <stdio.h>
#include <AtlBase.h>
#include <AtlCom.h>
#include <UIAutomation.h>

//this method fails if browser is in full-screen mode
bool find_url(IUIAutomation* uia, IUIAutomationElement* root)
{
    // The root window has several childs, 
    // one of them is a "pane" named "Google Chrome"
    // This contains the toolbar. Find this "Google Chrome" pane:
    CComPtr<IUIAutomationElement> pane;
    CComPtr<IUIAutomationCondition> pane_cond;
    uia->CreatePropertyCondition(UIA_ControlTypePropertyId,
        CComVariant(UIA_PaneControlTypeId), &pane_cond);

    CComPtr<IUIAutomationElementArray> arr;
    if FAILED(root->FindAll(TreeScope_Children, pane_cond, &arr))
        return false;

    int count = 0;
    arr->get_Length(&count);
    for (int i = 0; i < count; i++)
    {
        CComBSTR name;
        if SUCCEEDED(arr->GetElement(i, &pane))
            if SUCCEEDED(pane->get_CurrentName(&name))
                if (wcscmp(name, L"Google Chrome") == 0)
                    break;
        pane.Release();
    }

    if (!pane)
        return false;

    //look for first UIA_EditControlTypeId under "Google Chrome" pane
    CComPtr<IUIAutomationElement> url;
    CComPtr<IUIAutomationCondition> url_cond;
    uia->CreatePropertyCondition(UIA_ControlTypePropertyId, 
        CComVariant(UIA_EditControlTypeId), &url_cond);
    if FAILED(pane->FindFirst(TreeScope_Descendants, url_cond, &url))
        return false;

    //get value of `url`
    CComVariant var;
    if FAILED(url->GetCurrentPropertyValue(UIA_ValueValuePropertyId, &var)) 
        return false;
    if (!var.bstrVal)
        return false;
    wprintf(L"find_url: %s\n", var.bstrVal);

    //set new address ...
    IValueProvider* pattern = nullptr;
    if (FAILED(url->GetCurrentPattern(UIA_ValuePatternId, (IUnknown**)&pattern)))
        return false;
    //pattern->SetValue(L"somewhere.com");
    pattern->Release();

    INPUT input[2] = { INPUT_KEYBOARD };
    input[0].ki.wVk = VK_RETURN;
    input[1] = input[0];
    input[1].ki.dwFlags |= KEYEVENTF_KEYUP;
    SendInput(2, input, sizeof(INPUT));

    return true;
}
    
int main()
{
    //find the first visible chrome window
    HWND hwnd = nullptr;
    while (true)
    {
        hwnd = FindWindowEx(nullptr, hwnd, L"Chrome_WidgetWin_1", nullptr);
        if (!hwnd)
            return 0;
        if (IsWindowVisible(hwnd) && GetWindowTextLength(hwnd) > 0)
            break;
    }

    //CoInitializeEx(nullptr, COINIT_MULTITHREADED);//<- pick the right one
    CoInitialize();
    CComPtr<IUIAutomation> uia;
    if SUCCEEDED(uia.CoCreateInstance(CLSID_CUIAutomation))
    {
        CComPtr<IUIAutomationElement> root;
        if SUCCEEDED(uia->ElementFromHandle(hwnd, &root))
            find_url(uia, root);
        uia.Release();
    }

    CoUninitialize();
    return 0;
}

【讨论】:

  • 在我的例子中,found 始终是NULL,这表明找不到"Address and search bar"。我错过了什么吗?我已经读过 chrome 应该以“--enable-accessibility --force-renderer-accessibility”参数开始,这也没有帮助。可能这些参数也已经过时了。
  • 你的代码和我的一模一样吗?也许“地址和搜索栏” 只是英文。我更新了答案以找到第一个编辑控件,或者找到带有整数 id 的编辑控件。使用计算机上的检查工具进行验证。 Inspect 可能已经安装在您的计算机上:C:\Program Files (x86)\Windows Kits\8.1\bin\x64\inspect.exe
  • 确实,这是一个本地化问题。我使用的是德国操作系统和 Chrome,在这种情况下,它被命名为 "Adress- und Suchleiste"。之前的代码适用于此更改。但是,此当前代码不起作用,因为第一个编辑控件的名称为空 "" 并且当我重新启动 chrome 时 id 似乎发生了变化。非常感谢,你真的很有帮助!
  • 那很好。我做了一些改进,你能用0xC354再试一次吗?之前有个问题。如果 Chrome 的任务管理器处于活动状态,它没有找到正确的选项卡。
  • 像魅力一样工作,没有本地化问题!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-24
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多