我找到了在 iOS 中做同样事情的方法。
我知道这不是您问题的直接答案,但我会尝试解释我为在 iOS 中找到它所做的工作,希望您能够在 macOS 中做同样的事情。此外,这可能对其他读者有用...
我首先猜测进程本身正在创建AXUIElementRef,因此当我请求具有AXUIElementRef 值的可访问性属性(例如kAXUIElementAttributeChildren)时,它必须创建它们。
然后我创建了一个应用程序,并 dlsym'ed _AXUIElementCreateAppElementWithPid(int pid),用 [[NSProcessInfo processInfo] processIdentifier] 调用它。
我收到了根AXUIElementRef,然后我将它传递给AXError AXUIElementCopyMultipleAttributeValues(AXUIElementRef element, CFArrayRef attributes, AXCopyMultipleAttributeOptions options, CFArrayRef _Nullable *values),请求kAXUIElementAttributeChildren,它工作了(应该在主线程上运行)!
我开始仔细调试汇编代码中的 AXUIElementCopyMultipleAttributeValues 调用,它非常像那样(这是非常伪代码,当然......):
// serialize the arguments for MIG call
if (axUIElementRef->pid == self pid) {
// that's good that we are calling our own process, we can easily keep debugging!
_MIGXAAXUIElementCopyMultipleAttributeValues(serialized arguments) {
// Get the original element from the AXUIElementRef:
UIView* view = _AXElementForAXUIElementUniqueId(id);
[view accessibilityAttributeValue:kAXUIElementAttributeChildren] {
[view _accessibilityUserTestingChildren] {
// since this is the UIApplication element, it just gets the windows:
NSArray*<UIWindow*> winArr = [(UIApplication*)view _accessibilityWindows];
// for each value in result, convert to AX value:
...
AXConvertOutgoingValue(winArr) {
// For each UIView, convert to AXUIElementRef:
AXUIElementRef e = _AXCreateAXUIElementWithElement(winArr[i]);
}
}
}
}
} else {
// Do the same only if we are entitled, and outside our process
}
因此,在 iOS 中,您只需调用 AXUIElementRef _AXCreateAXUIElementWithElement(UIView*); 即可将 UI 转换为可访问性元素,而 UIView* _AXElementForAXUIElementUniqueId(AXUIElementRefGetUniqueID(AXUIElementRef)); 则相反。
所有符号均来自AXRuntime.framework。
在 mac 中,您需要链接 ApplicationServices.framework 并尝试类似的操作。
希望这会有所帮助...