You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

macOS Accessibility API在CLI/FFI场景下无法获取其他应用信息的问题

macOS Accessibility API 命令行/FFI调用问题排查方向

1. 权限上下文差异

SwiftUI应用属于GUI应用范畴,权限授权后直接生效;但命令行工具、Rust二进制这类非GUI进程,权限生效逻辑不同:

  • 确保终端本身已在「系统设置 > 隐私与安全性 > 辅助功能」列表中(如果直接在终端运行命令行工具);
  • 若通过Rust FFI调用,需将Rust编译出的二进制文件添加到辅助功能授权列表中,而非仅授权Swift库或SwiftUI应用;
  • 授权后重启进程或终端,避免权限缓存导致的生效延迟。

2. 避免依赖全局焦点元素

命令行环境下,kAXFocusedUIElementAttribute可能指向终端自身而非目标应用,导致cannotComplete错误。建议直接指定目标应用PID获取元素:

// 获取Messages应用的PID
guard let pid = NSWorkspace.shared.runningApplications.first(where: { $0.bundleIdentifier == "com.apple.Messages" })?.processIdentifier else {
    print("未找到目标应用")
    return
}
// 创建目标应用的AXUIElement
let appElement = AXUIElementCreateApplication(pid)
// 直接读取选中文本
var selectedText: AnyObject?
let status = AXUIElementCopyAttributeValue(appElement, kAXSelectedTextAttribute as CFString, &selectedText)
if status == .success, let text = selectedText as? String {
    print("选中文本:\(text)")
} else {
    print("获取失败,状态码:\(status.rawValue)")
}

3. 准确验证权限状态

不要仅依赖AXIsProcessTrusted()返回的true,改用AXIsProcessTrustedWithOptions()验证实际权限(支持自动弹出授权窗口):

let options: [String: Any] = [kAXTrustedCheckOptionPrompt.takeRetainedValue() as String: true]
let isTrusted = AXIsProcessTrustedWithOptions(options as CFDictionary)
print("实际权限状态:\(isTrusted)")

如果调用后弹出授权窗口,说明之前的权限未正确生效,完成授权后重试即可。

4. 签名与Entitlements配置

  • 命令行工具需在Xcode项目中开启「辅助功能」权限:进入项目设置 > Signing & Capabilities > 添加「Accessibility」Capability;
  • Rust二进制文件需添加com.apple.security.accessibility entitlement,可通过签名工具添加:
    codesign --entitlements entitlements.plist -f /path/to/rust-binary
    
    其中entitlements.plist内容为:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>com.apple.security.accessibility</key>
        <true/>
    </dict>
    </plist>
    

5. 确保目标应用处于激活状态

命令行执行时,目标应用可能未处于前台激活状态,导致无法读取其UI元素。可在调用API前激活目标应用:

if let app = NSWorkspace.shared.runningApplications.first(where: { $0.bundleIdentifier == "com.apple.Messages" }) {
    app.activate(options: .activateIgnoringOtherApps)
    // 短暂等待激活完成
    Thread.sleep(forTimeInterval: 0.5)
}

内容的提问来源于stack exchange,提问作者ihales

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 17:28:13