Reputation: 172
I have used AppleScript to get selected text from third party app. Which is working fine in osx 10.13 but stopped working in osx 10.14.
From searching, got one suggestion to add "NSAppleEventsUsageDescription" in info.plist, but that is also not working for me.
let latestApp = "Safari"
//Write script to activate the app and get the selected text to our app
let script = """
tell application \"\(latestApp)\"
activate
end tell
tell application \"System Events\"
tell process \"\(latestApp)\"
keystroke \"c\" using {command down}
delay 0.1
set myData to (the clipboard) as text
return myData
end tell
end tell
"""
let scriptObject = NSAppleScript.init(source: script)
let errorDict: AutoreleasingUnsafeMutablePointer<NSDictionary?>? = nil
var returnDescription:NSAppleEventDescriptor? = nil
returnDescription = scriptObject?.executeAndReturnError(errorDict)
if( returnDescription != nil ){
if( kAENullEvent != returnDescription?.descriptorType ){ //successful execution
if( cAEList == returnDescription?.descriptorType ){
print("return value")
}else{
print("Returned string : \(String(describing: returnDescription?.stringValue))")
let selectedStr = returnDescription?.stringValue!
if( (selectedStr?.count)! > 0 ){
print("selectedStr is :\(String(describing: selectedStr))")
}
}
}
}else{
print("Error is : \(String(describing: errorDict))")
}
It works perfectly in os 10.12 & 10.13 & ScriptEditor also.
Upvotes: 1
Views: 878
Reputation: 3142
Since you are telling "Safari" to activate, having "System Events" to tell process "Safari"
... Is not necessary. Simply using "System Events"
to keystroke "c" using {command down}
accomplishes the same thing. It's not a huge deal but eliminating unnecessary lines of code here and there, makes navigating through code easier and cleaner. In addition, without adding an additional delay 0.3
before the keystroke "c" using {command down}
command, returned an empty clipboard on my system 50% of the time.
This AppleScript code works for me using the latest version of macOS Mojave.
tell application "Safari" to activate
delay 0.2 -- Adjust As Needed
tell application "System Events" to keystroke "c" using {command down}
set myData to (the clipboard) as text
Since clipboard
commands are handled by Standard Additions and not System Events (as mentioned by @user3439894 in his comment), removing set myData to (the clipboard) as text
from the System Events
tell block, allowed me to successfully remove the delay 0.1
command.
OR OPTION 2
Actually, on second thought, if you are looking to only use this in Safari, this following one line of AppleScript code will do what you need.
You must enable the Allow JavaScript from Apple Events option in Safari's Develop menu to use do JavaScript
.
tell application "Safari" to set myData to (do JavaScript "''+document.getSelection()" in document 1)
I have only addressed the AppleScript part because @matt thoroughly covered every other issue in his post.
Upvotes: 4
Reputation: 535925
You say "it worked perfectly" in previous systems. I find that difficult to believe, since almost everything about your code is wrong. I corrected your code and got your script to work, with very little difficulty.
I'll try to describe what I did.
To prepare the ground, I ran a version of your script in Script Editor (removing the backslashes and string interpolation of course):
tell application "Safari"
activate
end tell
tell application "System Events"
tell process "Safari.app"
keystroke "c" using {command down}
delay 0.1
set myData to (the clipboard) as text
return myData
end tell
end tell
The script didn't run at first, but a dialog sent me to System Preferences -> Security & Privacy -> Accessibility, where I checked Script Editor and System Events.
Now I was ready to create the app. My app is called AnotherAppleScriptExample. In its entitlements, sandboxing is NO.
In its Info.plist is this entry:
My version of your code (fixing the various Swift mistakes) is this:
let app = "Safari.app"
let script = """
tell application "\(app)"
activate
end tell
tell application "System Events"
tell process "\(app)"
keystroke "c" using {command down}
delay 0.1
set myData to (the clipboard) as text
return myData
end tell
end tell
"""
if let scriptObject = NSAppleScript(source: script) {
var error: NSDictionary? = nil
let result = scriptObject.executeAndReturnError(&error)
if( kAENullEvent != result.descriptorType ){
print(result.stringValue as Any)
}
}
I ran the app. I got two dialogs. First this:
I clicked OK. Then this:
I clicked Open System Preferences. In System Preferences, I checked my app (now both System Events and my app are checked):
Now the ground is fully prepared. I quit the app and ran it again. The script worked correctly, printing the selection in Safari.
Upvotes: 2