Execute Applescript from Cocoa App with params

帅比萌擦擦* 提交于 2019-12-06 09:22:04

问题


I would like to know how to execute an applescript from a cocoa application passing parameters. I have seen how easy is to execute applescripts with no parameters in other questions here at stackoverflow, however the use NSAppleScript class, in which, i haven't seen no method that solve my problem. Does anyone have any idea.

I would like a Cocoa code with the same effect o this shell:

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

So it may run this 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

Any help is appreciated. Thanks in advance.


回答1:


Look at my GitHub repository, I have a category of NSAppleEventDescriptor that makes it much easier to create NSAppleEventDescriptor to call different AppleScript procedures with arguments, and coercion to and from many AppleScript typed.

NSAppleEventDescriptor-NDCoercion




回答2:


I found easier to follow this piece code. I took a code from here and modified it to my purpose.

 - (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;
}



回答3:


I'm not all too familiar with AppleScript, but I seem to remember that they are heavily based on (the rather crappy) Apple Events mechanism which dates back to the days where the 56k Modem was the coolest Gadget in your house.

Therefore I'd guess that you're looking for executeAppleEvent:error: which is part of NSAppleScript. Maybe you can find some information on how to encapsulate execution arguments in the instance of NSAppleEventDescriptor that you have to pass along with this function.




回答4:


Technical Note TN2084

Using AppleScript Scripts in Cocoa Applications

Even though your application is written in Objective-C using Cocoa, you can use AppleScript scripts to perform certain operations. This Technical Note explains how to integrate and execute AppleScripts from within your Cocoa application. It discusses how to leverage the NSAppleScript class and the use of NSAppleEventDescriptor to send data to the receiver.

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 version, modified from the code here:
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)")
    }
}

For running the apple script:

on MyMethodName(theParameter)
    display dialog theParameter
end MyMethodName


来源:https://stackoverflow.com/questions/6963072/execute-applescript-from-cocoa-app-with-params

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!