首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >get_accChildCount在不应该返回0时返回0

get_accChildCount在不应该返回0时返回0
EN

Stack Overflow用户
提问于 2016-05-26 10:53:24
回答 1查看 359关注 0票数 2

我试图从一个扩展和一个独立的应用程序中枚举IE的选项卡。对于其中一个MSAA节点,当从扩展调用时,get_accChildCount返回0,而它应该根据inspect返回1和从独立应用程序返回调用。

  • 之前在StackOverflow上描述了这个问题,但它是通过一次对我不起作用的黑客来解决的。/clr/MT是不兼容的。
  • 还有MSDN专题也有同样的问题。那里没有唯一的答案。
  • 如果您以管理员权限运行IE,它将正常工作。
  • API监视器在一个极小的例子中显示了数千次调用,目前还不清楚这些调用中哪些是相关的。下面是最小的例子。

get_accChildCount返回错误的子计数时,有哪些无文档的情况?

在IE的大多数版本中,我还能用什么其他方法来激活选项卡呢?

代码语言:javascript
复制
#include <atlbase.h>
#include <atlcom.h>
#include <atlctl.h>
#include <atltypes.h>
#include <atlsafe.h>
#include <io.h>
#include <fcntl.h>
#include <windows.h>

#include <iostream>
#include <string>
#include <vector>
#include <boost/format.hpp>
#include <fstream>
using namespace std;

CComPtr<IAccessible> get_acc_by_hwnd(HWND hwnd) {
    CComPtr<IAccessible> ret;
    HRESULT hr = ::AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible, (void**) &ret);
    if (FAILED(hr) || !ret) {
        wcout << L"Accessible::Accessible invalid hwnd" << endl;
    }
    return ret;
}

std::vector<CComPtr<IAccessible>> get_acc_children(CComPtr<IAccessible> acc) {
    std::vector<CComPtr<IAccessible>> ret;
    long count;
    if (FAILED(acc->get_accChildCount(&count))) return ret;
    long count_obtained = 0;
    if (!count) return ret;
    std::vector<CComVariant> accessors(count);
    if (FAILED(::AccessibleChildren(acc, 0, count, &*accessors.begin(), &count_obtained))) return ret;
    accessors.resize(count_obtained);
    for (auto vtChild : accessors) {
        if (vtChild.vt != VT_DISPATCH) continue;
        CComQIPtr<IAccessible> pChild = vtChild.pdispVal;
        if (pChild) ret.push_back(pChild);
    }
    return ret;
}

bool is_client(CComPtr<IAccessible> acc) {
    CComVariant var;
    HRESULT hr = acc->get_accRole(CComVariant(CHILDID_SELF), &var);
    return SUCCEEDED(hr) && var.vt == VT_I4 && var.lVal == 0xA;
}

std::wstring get_descr(CComPtr<IAccessible> acc) {
    CComBSTR str;
    HRESULT hr = acc->get_accDescription(CComVariant(CHILDID_SELF), &str);
    return SUCCEEDED(hr) && str ? std::wstring(str) : L"";
}

int main() {
    ::CoInitialize(nullptr);
    _setmode(_fileno(stdout), _O_U16TEXT);

    // put HWND of the window that contains tab labels
    // it's hardcoded to minimize quantity of API calls
    HWND hwnd = reinterpret_cast<HWND>(0x002D0696);
    CComPtr<IAccessible> iaccessible;
    HRESULT hr = ::AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible, (void**) &iaccessible);
    if (FAILED(hr) || !iaccessible) {
        wcout << L"AccessibleBrowser::activate_tab " L"failed to get IAccessible for IE" << endl;
        return EXIT_FAILURE;
    }

    wstring const sentinel = L"\r\n";
    for (auto child : get_acc_children(iaccessible)) if (is_client(child)) {
        for (auto child1 : get_acc_children(child)) { // fails here in extension
            for (auto child2 : get_acc_children(child1)) {
                std::wstring descr = get_descr(child2);
                auto pos = descr.find(sentinel);
                if (pos == string::npos) continue;
                auto tab_url = descr.substr(pos + sentinel.size());
                wcout << tab_url << endl;
            }
        }
    }
}
EN

回答 1

Stack Overflow用户

发布于 2016-05-29 02:33:02

我戳了你的节目一段时间,没有什么可展示的。也许我意识到太晚了,它不应该重现这个问题:(我只能提供一些可能有用的提示,让你在正确的岩石下面寻找。)

但它是通过一次对我不起作用的黑客来解决的

这些程序员犯了一个简单的错误,他们忘了打电话给CoInitialize/Ex()。很常见的疏忽。使用/clr构建选项可以避免这个错误,因为现在调用它的是CLR。您可以轻松地复制这一不幸,只需注释掉CoInitialize()调用即可。不幸的是,它工作了一段时间,没有产生任何响亮的错误,但是对于某些accobjects,您确实得到了0。您会注意到您的程序不再找到选项卡。

不太确定我是否能清楚地解释这一点,某些COM样式的对象模型实际上并不使用COM基础结构。DirectX是最好的例子,我们可以将UIAutomation添加到这个列表中。当客户端应用程序的组件是基于COM的时,我猜想它会像这样默默地失败。不清楚是否是,DirectUIHWnd是完全没有文件的。

因此,停止寻找它作为一个解决方案,您没有忘记调用CoInitialize(),它将由IE在激活您的扩展之前处理。

如果您以管理员权限运行IE,它将正常工作。

那是块更好的石头。许多程序员一直在运行VS,在UIA的情况下,角色可能会被逆转。请记住,您的扩展在IE内部的沙箱中运行。没有真正的想法,提升IE如何影响这一点。在运行在低完整性沙箱中的代码中,您不能做的一件事是戳到运行在较高完整性模式下的代码所拥有的UI组件。谷歌“禁用IE增强保护模式”,并遵循指导方针,看看这对你的加载项有什么影响。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37458778

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档