在macOS High Sierra中通过AXUIElementRef获取的窗口列表始终为空
嘿,这个问题我太熟了!升级到macOS High Sierra后,好多开发者都栽在辅助功能权限的收紧上,你的代码失效大概率就是这个原因~
问题根源:Accessibility权限管控升级
从High Sierra开始,苹果对辅助功能(Accessibility)的权限规则做了更严格的限制。哪怕你之前的程序已经获得了权限,升级后系统可能会重置权限,或者新的规则要求你重新授权,导致AXUIElement相关的API调用直接失败。
一步步解决问题
1. 先给你的程序开辅助功能权限
这是最关键的一步:
- 打开「系统偏好设置」→「安全性与隐私」→切换到「隐私」标签
- 在左侧列表找到「辅助功能」,然后点击右下角的锁图标解锁(需要输入密码)
- 点击列表下方的「+」号,找到你的应用程序(如果是Xcode调试的话,要选你的目标程序或者Xcode本身;如果是命令行工具,找到你的可执行文件或者终端程序),勾选它
- 划重点:勾选后最好重启你的应用/Xcode/终端,不然权限可能不生效
2. 给代码加上错误处理,排查具体问题
你原来的代码没写错误检查,根本不知道哪里出问题。我给你补全了错误处理的版本,能清晰看到失败原因:
#import <Foundation/Foundation.h> #import <CoreFoundation/CoreFoundation.h> #import <ApplicationServices/ApplicationServices.h> int main(int argc, const char * argv[]) { @autoreleasepool { pid_t targetPID = 311; // 替换成你要查询的应用PID AXUIElementRef appRef = AXUIElementCreateApplication(targetPID); CFArrayRef windowList = NULL; AXError error = AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute, (CFTypeRef *)&windowList); // 检查API调用是否成功 if (error != kAXErrorSuccess) { NSLog(@"获取窗口列表失败!错误码:%d", error); // 常见错误码对应问题: // kAXErrorNotAuthorized (0x10000) → 权限没开或者没生效 // kAXErrorInvalidUIElement (0x10001) → 目标PID的应用不存在或者无效 CFRelease(appRef); return 1; } // 遍历窗口列表,获取窗口信息 NSInteger windowCount = CFArrayGetCount(windowList); NSLog(@"找到 %ld 个窗口", windowCount); for (NSInteger i = 0; i < windowCount; i++) { AXUIElementRef windowElement = CFArrayGetValueAtIndex(windowList, i); // 示例:获取窗口标题 CFStringRef windowTitle = NULL; if (AXUIElementCopyAttributeValue(windowElement, kAXTitleAttribute, (CFTypeRef *)&windowTitle) == kAXErrorSuccess && windowTitle) { NSLog(@"窗口 %ld:%@", i+1, (__bridge NSString *)windowTitle); CFRelease(windowTitle); } CFRelease(windowElement); } // 别忘了释放CF对象,避免内存泄漏 CFRelease(windowList); CFRelease(appRef); } return 0; }
3. 命令行工具的特殊注意事项
如果你是在终端里运行这个程序:
- 要确保你的终端(比如Terminal.app或iTerm)已经被添加到辅助功能列表里
- 如果用
sudo运行,权限会继承root环境,这时候可能需要给root用户也配置辅助功能(但尽量别用sudo,优先让普通用户权限生效) - 权限更改后一定要重启终端,不然可能还是会提示未授权
额外小贴士
- 如果错误码是
kAXErrorNotAuthorized,别怀疑,就是权限没配对,再仔细检查辅助功能列表里有没有你的程序 - 有些系统自带应用(比如Finder)的权限生效可能需要重启系统
- 调试的时候,Xcode的调试目标有时候会被系统识别为新程序,需要重新勾选权限
内容的提问来源于stack exchange,提问作者Jlegend
相关产品推荐
相关产品推荐

