gpt4 book ai didi

c++ - get_accChildCount 在不应该的时候返回 0

转载 作者:行者123 更新时间:2023-11-30 03:41:18 25 4
gpt4 key购买 nike

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

  • 描述了问题previously在 StackOverflow,但它是通过对我不起作用的 hack 解决的。 /clr/MT 不兼容。
  • 还有a topic on MSDN有同样的问题。那里没有单一的答案。
  • 如果您以管理员权限运行 IE,它可以正常工作。
  • API Monitor在一个最小示例中显示了数千个调用,并且不清楚其中哪些是相关的。下面附上了最小示例。

get_accChildCount 返回错误的子计数时,有哪些未记录的情况?

在大多数版本的 IE 中,我可以使用什么其他方法通过 URL 激活选项卡?

#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;
}
}
}
}

最佳答案

我查看了您的程序一段时间,但没有什么可展示的。也许我意识到它不应该重现该问题为时已晚:(我只能提供一些可能有用的提示,让您在正确的岩石下寻找。

yet it was solved via a hack that doesn't work for me

这些程序员犯了一个简单的错误,他们忘记调用CoInitialize/Ex()。一个非常普遍的疏忽。使用/clr 构建选项可以解决该错误,因为现在调用它的是 CLR。您可以轻松重现此错误,只需注释掉 CoInitialize() 调用即可。不幸的是,它工作了一段时间而没有产生任何大的错误,但是对于某些 accobjects 你确实得到了 0。您会注意到您的程序不再找到这些选项卡。

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

所以不要再寻找解决方法了,您没有忘记调用 CoInitialize(),IE 会在激活您的扩展之前处理它。

If you run IE with administrator privileges, it works properly.

那是一 block 更好的石头。许多程序员一直运行 VS 提升,在 UIA 的情况下,角色可能会颠倒。请记住,您的扩展在 IE 内的沙箱中运行。不知道提升 IE 对此有何影响。对于在低完整性沙箱中运行的代码,您不能做的一件事是戳在更高完整性模式下运行的代码所拥有的 UI 组件。谷歌“禁用 IE 增强保护模式”并按照指南查看对您的插件有何影响。

关于c++ - get_accChildCount 在不应该的时候返回 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37458778/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com