swift applescript

¿Puede ejecutar un script de Apple desde una aplicación Swift?



applescript (6)

A partir de marzo de 2018, creo que la respuesta más fuerte en este hilo sigue siendo la respuesta aceptada de 2011 . Las implementaciones que implicaron el uso de NSAppleScript u OSAScript sufrieron los inconvenientes de tener algunas pérdidas de memoria menores, pero muy desagradables, sin proporcionar realmente ningún beneficio adicional. Cualquiera que tenga dificultades para conseguir que la respuesta se ejecute correctamente (en Swift 4) puede intentar esto:

let manager = FileManager() // Note that this assumes your .scpt file is located somewhere in the Documents directory let script: URL? = try? manager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) if let scriptPath = script?.appendingPathComponent("/path/to/scriptName").appendingPathExtension("scpt").path { let process = Process() if process.isRunning == false { let pipe = Pipe() process.launchPath = "/usr/bin/osascript" process.arguments = [scriptPath] process.standardError = pipe process.launch() } }

Tengo un simple AppleScript que envía un correo electrónico. ¿Cómo puedo llamarlo desde una aplicación Swift?

(No pude encontrar la respuesta a través de Google).


Como sugiere Kamaros , puede llamar a NSApplescript directamente sin tener que iniciar un proceso separado a través de NSTask (como sugiere CRGreen ).

código SWIFT

let myAppleScript = "..." var error: NSDictionary? if let scriptObject = NSAppleScript(source: myAppleScript) { if let output: NSAppleEventDescriptor = scriptObject.executeAndReturnError( &error) { print(output.stringValue) } else if (error != nil) { print("error: /(error)") } }


Luché pocas horas, pero nada funcionó. Finalmente logré ejecutar AppleScript a través de shell:

let proc = Process() proc.launchPath = "/usr/bin/env" proc.arguments = ["/usr/bin/osascript", "scriptPath"] proc.launch()

Dunno es esta la mejor manera de hacerlo, pero al menos funciona.


No probado, pero parece que uno puede hacer algo como (se agregó una ruta de acceso de script arbitraria):

import Foundation let task = NSTask() task.launchPath = "/usr/bin/osascript" task.arguments = ["~/Desktop/testscript.scpt"] task.launch()


Para cualquiera que reciba la siguiente advertencia para Swift 4 , para la línea mientras crea un NSAppleEventDescriptor de la respuesta de zekel

Expresión no opcional de tipo ''NSAppleEventDescriptor'' utilizada en una verificación de opciones

Puedes deshacerte de él con esta versión corta editada:

let myAppleScript = "..." var error: NSDictionary? if let scriptObject = NSAppleScript(source: myAppleScript) { if let outputString = scriptObject.executeAndReturnError(&error).stringValue { print(outputString) } else if (error != nil) { print("error: ", error!) } }

Sin embargo , puede que también te hayas dado cuenta; con este método, el sistema registra este mensaje en la consola cada vez que ejecuta el script:

AppleEvents: recibió mensajes de máquina que no eran del tipo complejo como se esperaba en getMemoryReference.

Aparentemente, es un error declarado por un desarrollador del personal de Apple, y se dice que es ''solo'' un spam de registro inofensivo y está programado para ser eliminado en futuras actualizaciones del sistema operativo, como se puede ver en este extenso post del foro de desarrolladores de Apple y en la pregunta SO abajo:

AppleEvents: recibió mensajes de máquina que no eran del tipo complejo como se esperaba en getMemoryReference

Gracias Apple, por esos bazillones de registros de consolas basura tirados por ahí.


Puede probar NSAppleScript, de la Nota técnica TN2084 de Apple Uso de scripts AppleScript en aplicaciones Cocoa https://developer.apple.com/library/mac/technotes/tn2084/_index.html

NSAppleScript* scriptObject = [[NSAppleScript alloc] initWithSource: @"/ set app_path to path to me/n/ tell application /"System Events/"/n/ if /"AddLoginItem/" is not in (name of every login item) then/n/ make login item at end with properties {hidden:false, path:app_path}/n/ end if/n/ end tell"]; returnDescriptor = [scriptObject executeAndReturnError: &errorDict];