Swift4: `AXUIElementCopyAttributeValue()` returns `AXError.cannotComplete`
Asked Answered
B

1

7

On running the following code:

let pid = getAppPid()
let AXApp = AXUIElementCreateApplication(pid)

var children: CFTypeRef?
let returnVal = AXUIElementCopyAttributeValue(AXApp,
    kAXChildrenAttribute as CFString, &children)
  • AXApp gets created successfully

However

  • children is nil
  • returnVal is AXError.cannotComplete ("A fundamental error has occurred, such as a failure to allocate memory during processing.")

I've seen code on stack overflow and elsewhere using exactly the same method as I am.

What am I missing.

I am using Xcode 9/Swift 4 on MacOS High Sierra.

EDIT:

I should add that Xcode has accessibility permissions, and I am able to successfully do other stuff that requires accessibility permission like CGEvent.tapCreate() to monitor global keyboard events etc.

Blakey answered 6/11, 2017 at 19:13 Comment(5)
Switch off sandboxing. How to use Accessibility with sandboxed app?Atlantis
Thanks, that works. If you add that as answer, I'll mark it as the right one.Blakey
Also: I was able to get it working by setting the App Sandbox key to NO in the .entitlements file. I this the best way? I couldn't find a key to just request entitlement for accessibility, while preserving the rest of the sandbox compliance features. Do you know if some thing like that exists? Thanks.Blakey
I don't know anything about App Sandbox. I managed to switch it off but that's it.Atlantis
cool, I am doing the same. do you want to put your initial comment as an answer?Blakey
T
0

To fix this error you should turn off App Sandbox by doing the following:

You can turn off Sandboxing by removing it from the Signing & Capabilities tab:

enter image description here

After that AXError.cannotComplete should not appear again. If you still get some issues you can try to get the selected text of the frontmost app like this:

import ApplicationServices
import Cocoa

func getSelectedText() -> String? {
    let systemWideElement = AXUIElementCreateSystemWide()

    var selectedTextValue: AnyObject?
    let errorCode = AXUIElementCopyAttributeValue(systemWideElement, kAXFocusedUIElementAttribute as CFString, &selectedTextValue)
    
    if errorCode == .success {
        let selectedTextElement = selectedTextValue as! AXUIElement
        var selectedText: AnyObject?
        let textErrorCode = AXUIElementCopyAttributeValue(selectedTextElement, kAXSelectedTextAttribute as CFString, &selectedText)
        
        if textErrorCode == .success, let selectedTextString = selectedText as? String {
            return selectedTextString
        } else {
            return nil
        }
    } else {
        print(errorCode.rawValue)
        return nil
    }
}
Tillich answered 23/8 at 15:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.