使用params从Cocoa App执行Applescript

时间:2011-08-05 22:02:08

标签: cocoa applescript

我想知道如何从传递参数的cocoa应用程序中执行applescript。 我已经看到在stackoverflow中执行其他问题中没有参数的applescripts是多么容易,但是使用NSAppleScript类,其中,我没有看到没有解决我的问题的方法。有没有人有任何想法。

我想要一个与此shell具有相同效果的Cocoa代码:

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 个答案:

答案 0 :(得分:4)

查看我的GitHub存储库,我有一个NSAppleEventDescriptor类别,它可以更容易地创建NSAppleEventDescriptor来调用带有参数的不同AppleScript过程,以及对许多AppleScript类型进行强制操作。

NSAppleEventDescriptor-NDCoercion

答案 1 :(得分:3)

我发现更容易遵循这段代码。我从here获取了一段代码并将其修改为我的目的。

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

答案 2 :(得分:1)

我对AppleScript并不是很熟悉,但我似乎记得它们基于(相当蹩脚的) Apple Events 机制,其历史可以追溯到56k调制解调器的时代。你房子里最酷的小工具。

因此,我猜您正在寻找属于NSAppleScript的{​​{3}}。也许你可以找到一些关于如何在NSAppleEventDescriptor的实例中封装执行参数的信息,你必须传递这个函数。

答案 3 :(得分:0)

  

技术说明TN2084

     

在可可应用程序中使用AppleScript脚本

     

即使使用Cocoa用Objective-C编写应用程序,也可以使用AppleScript脚本执行某些操作。本技术说明介绍了如何在Cocoa应用程序中集成和执行AppleScript。它讨论了如何利用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