web-dev-qa-db-fra.com

Pouvez-vous exécuter un script Applescript à partir d'une application Swift

J'ai un simple AppleScript qui envoie un e-mail. Comment puis-je l'appeler depuis une application Swift?

(Je n'ai pas pu trouver la réponse via Google.)

26
codingguy3000

Non testé, mais il semble que l'on puisse faire quelque chose comme (chemin de script arbitraire ajouté):

import Foundation

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

task.launch()

[MISE À JOUR C'est maintenant 2019 et il y a probablement eu un certain nombre de problèmes et de changements au cours des dernières années. Voici le code mis à jour que je viens de tester sur ma machine, qui est sur OSX Mojave 10.14.5]

ObjC.import('Foundation');

let task = $.NSTask.alloc.init;
task.launchPath = "/usr/bin/osascript";
task.arguments = ["/testing_folder/test.scpt"];

task.launch
23
CRGreen

Comme Kamaros suggère , vous pouvez appeler NSApplescript directement sans avoir à lancer un processus séparé via NSTask (comme CRGreen suggère .)

Code 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)")
    }
}
55
zekel

Pour tous ceux qui reçoivent l'avertissement ci-dessous pour Swift 4 , pour la ligne lors de la création d'un NSAppleEventDescriptor à partir de réponse de zekel

Expression non facultative de type "NSAppleEventDescriptor" utilisée dans une vérification des options

Vous pouvez vous en débarrasser avec cette version courte éditée:

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!)
    }
}

Cependant , vous avez peut-être aussi réalisé; avec cette méthode, le système enregistre ce message sur la console chaque fois que vous exécutez le script:

AppleEvents: reçu un msg mach qui n'était pas de type complexe comme prévu dans getMemoryReference.

Apparemment, il s'agit d'un bogue déclaré par un Apple personnel, et il est dit qu'il est "juste" un spam de journal inoffensif et est prévu pour être supprimé sur les futures mises à jour du système d'exploitation, comme vous pouvez le voir dans ce très long message du forum des développeurs Apple et SO = question ci-dessous:

AppleEvents: reçu un msg mach qui n'était pas de type complexe comme prévu dans getMemoryReference

Merci Apple, pour ces bazillions de journaux de consoles indésirables jetés.

3
loopbender

En mars 2018, je pense que la réponse la plus forte sur ce sujet est toujours la réponse acceptée de 2011 . Les implémentations qui impliquaient l'utilisation de NSAppleScript ou OSAScript ont souffert des inconvénients ayant des fuites de mémoire mineures, mais très désagréables, sans vraiment apporter d'avantages supplémentaires. Quiconque a du mal à obtenir que cette réponse s'exécute correctement (dans Swift 4) peut vouloir essayer ceci:

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()
    }
}
3
Ben

J'ai lutté quelques heures, mais rien n'a fonctionné. Enfin, j'ai réussi à exécuter AppleScript via Shell:

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

Dunno est la meilleure façon de le faire, mais au moins cela fonctionne.

2
user4646361

Vous pouvez essayer NSAppleScript, à partir de la note technique TN2084 d'Apple Utilisation de scripts AppleScript dans les applications 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];
2
Yongxu Ren