Выполнить Applescript из приложения Какао с параметрами - PullRequest
2 голосов
/ 06 августа 2011

Я хотел бы знать, как выполнить appleScript из приложения-какао, передавая параметры.Я видел, как легко выполнять applecripts без параметров в других вопросах здесь, в stackoverflow, однако использовать класс NSAppleScript, в котором я не видел ни одного метода, который бы решал мою проблему.Кто-нибудь имеет какие-либо идеи.

Я хотел бы код Какао с тем же эффектом o этой оболочки:

osascript teste.applescript "snow:Users:MyUser:Desktop:MyFolder" "snow:Users:MyUser:Desktop:Example:" 

Так что он может запустить этот AppleScript.

on run argv

    set source to (item 1 of argv)

    set destiny to (item 2 of argv)

    tell application "Finder" to make new alias file at destiny to source
    0

end run

Любая помощь приветствуется.Заранее спасибо.

Ответы [ 4 ]

4 голосов
/ 06 августа 2011

Посмотрите на мой репозиторий GitHub, у меня есть категория NSAppleEventDescriptor, которая значительно упрощает создание NSAppleEventDescriptor для вызова различных процедур AppleScript с аргументами, а также для приведения ко многим типам AppleScript и обратно.

NSAppleEventDescriptor-NDCoercion

3 голосов
/ 10 августа 2011

Мне было проще следовать этому коду.Я взял код из здесь и изменил его для своей цели.

 - (BOOL) executeScriptWithPath:(NSString*)path function:(NSString*)functionName andArguments:(NSArray*)scriptArgumentArray
{
    BOOL executionSucceed = NO;

    NSAppleScript           * appleScript;
    NSAppleEventDescriptor  * thisApplication, *containerEvent;
    NSURL                   * pathURL = [NSURL fileURLWithPath:path];

    NSDictionary * appleScriptCreationError = nil;
    appleScript = [[NSAppleScript alloc] initWithContentsOfURL:pathURL error:&appleScriptCreationError];

    if (appleScriptCreationError)
    {
        NSLog([NSString stringWithFormat:@"Could not instantiate applescript %@",appleScriptCreationError]);
    }
    else 
    {
        if (functionName && [functionName length])
        {
            /* If we have a functionName (and potentially arguments), we build
             * an NSAppleEvent to execute the script. */

            //Get a descriptor for ourself
            int pid = [[NSProcessInfo processInfo] processIdentifier];
            thisApplication = [NSAppleEventDescriptor descriptorWithDescriptorType:typeKernelProcessID
                                                                             bytes:&pid
                                                                            length:sizeof(pid)];

            //Create the container event

            //We need these constants from the Carbon OpenScripting framework, but we don't actually need Carbon.framework...
            #define kASAppleScriptSuite 'ascr'
            #define kASSubroutineEvent  'psbr'
            #define keyASSubroutineName 'snam'
            containerEvent = [NSAppleEventDescriptor appleEventWithEventClass:kASAppleScriptSuite
                                                                      eventID:kASSubroutineEvent
                                                             targetDescriptor:thisApplication
                                                                     returnID:kAutoGenerateReturnID
                                                                transactionID:kAnyTransactionID];

            //Set the target function
            [containerEvent setParamDescriptor:[NSAppleEventDescriptor descriptorWithString:functionName]
                                    forKeyword:keyASSubroutineName];

            //Pass arguments - arguments is expecting an NSArray with only NSString objects
            if ([scriptArgumentArray count])
            {
                NSAppleEventDescriptor  *arguments = [[NSAppleEventDescriptor alloc] initListDescriptor];
                NSString                *object;

                for (object in scriptArgumentArray) {
                    [arguments insertDescriptor:[NSAppleEventDescriptor descriptorWithString:object]
                                        atIndex:([arguments numberOfItems] + 1)]; //This +1 seems wrong... but it's not
                }

                [containerEvent setParamDescriptor:arguments forKeyword:keyDirectObject];
                [arguments release];
            }

            //Execute the event
            NSDictionary * executionError = nil;
            NSAppleEventDescriptor * result = [appleScript executeAppleEvent:containerEvent error:&executionError];
            if (executionError != nil)
            {
                NSLog([NSString stringWithFormat:@"error while executing script. Error %@",executionError]);

            }
            else 
            {
                NSLog(@"Script execution has succeed. Result(%@)",result);          
                executionSucceed = YES;
            }
        } 
        else 
        {
            NSDictionary * executionError = nil;
            NSAppleEventDescriptor * result = [appleScript executeAndReturnError:&executionError];

            if (executionError != nil)
            {
                NSLog([NSString stringWithFormat:@"error while executing script. Error %@",executionError]);
            }
            else
            {
                NSLog(@"Script execution has succeed. Result(%@)",result);  
                executionSucceed = YES;
            }
        }
    }

    [appleScript release];  

    return executionSucceed;
}
1 голос
/ 06 августа 2011

Я не слишком знаком с AppleScript, но мне кажется, что я помню, что они в значительной степени основаны на (довольно дурацком) механизме Apple Events , который восходит ко временам, когда модем 56k был самый крутой гаджет в твоем доме.

Поэтому я бы предположил, что вы ищете executeAppleEvent: error: , которая является частью NSAppleScript. Возможно, вы можете найти некоторую информацию о том, как инкапсулировать аргументы выполнения в экземпляре NSAppleEventDescriptor, который вы должны передать вместе с этой функцией.

0 голосов
/ 25 сентября 2018

Техническое примечание TN2084

Использование сценариев AppleScript в приложениях для какао

Даже если ваше приложение написано на Objective-C с использованием Cocoa, вы можете использовать сценарии AppleScript для выполнения определенных операций. В этом техническом примечании объясняется, как интегрировать и выполнять сценарии AppleScripts из приложения Cocoa. В нем обсуждается, как использовать класс NSAppleScript и использовать NSAppleEventDescriptor для отправки данных получателю.

https://developer.apple.com/library/archive/technotes/tn2084/_index.html

https://applescriptlibrary.files.wordpress.com/2013/11/technical-note-tn2084-using-applescript-scripts-in-cocoa-applications.pdf

Версия Swift 4, модифицированная из кода здесь:
https://gist.github.com/chbeer/3666e4b7b2e71eb47b15eaae63d4192f

import Carbon

static func runAppleScript(_ url: URL) {
    var appleScriptError: NSDictionary? = nil
    guard let script = NSAppleScript(contentsOf: url, error: &appleScriptError) else {
        return
    }

    let message = NSAppleEventDescriptor(string: "String parameter")

    let parameters = NSAppleEventDescriptor(listDescriptor: ())
    parameters.insert(message, at: 1)

    var psn = ProcessSerialNumber(highLongOfPSN: UInt32(0), lowLongOfPSN: UInt32(kCurrentProcess))

    let target = NSAppleEventDescriptor(descriptorType: typeProcessSerialNumber, bytes: &psn, length: MemoryLayout<ProcessSerialNumber>.size)

    let handler = NSAppleEventDescriptor(string: "MyMethodName")

    let event = NSAppleEventDescriptor.appleEvent(withEventClass: AEEventClass(kASAppleScriptSuite), eventID: AEEventID(kASSubroutineEvent), targetDescriptor: target, returnID: AEReturnID(kAutoGenerateReturnID), transactionID: AETransactionID(kAnyTransactionID))

    event.setParam(handler, forKeyword: AEKeyword(keyASSubroutineName))
    event.setParam(parameters, forKeyword: AEKeyword(keyDirectObject))

    var executeError: NSDictionary? = nil
    script.executeAppleEvent(event, error: &executeError)

    if let executeError = executeError {
        print("ERROR: \(executeError)")
    }
}

Для запуска скрипта apple:

on MyMethodName(theParameter)
    display dialog theParameter
end MyMethodName
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...