2

I am writing sandboxed Mac OS X (10.10) app that should launch some Applescript. This is the script:

on terminal(params)
tell application "Terminal"
do script "who"
repeat with counter_variable_name from 1 to count of params
    set current_character to item counter_variable_name of params
    do script current_character in window 1
end repeat
end tell
end terminal

this is the code that prepares the invocation:

- (NSAppleEventDescriptor *)commandEventDescriptor:(NSString*) command withParams:(NSArray*)inputParams{
NSUInteger c=1;
NSAppleEventDescriptor *parameters = [NSAppleEventDescriptor listDescriptor];
for (NSString* s in inputParams) {
    NSAppleEventDescriptor *parameter = [NSAppleEventDescriptor descriptorWithString:s];
    [parameters insertDescriptor:parameter atIndex:c]; 
    parameter=nil;
    c++;
}

// target
ProcessSerialNumber psn = {0, kCurrentProcess};
NSAppleEventDescriptor *target = [NSAppleEventDescriptor descriptorWithDescriptorType:typeProcessSerialNumber bytes:&psn length:sizeof(ProcessSerialNumber)];

// function
NSAppleEventDescriptor *function = [NSAppleEventDescriptor descriptorWithString:command];

// event
NSAppleEventDescriptor *event = [NSAppleEventDescriptor appleEventWithEventClass:kASAppleScriptSuite eventID:kASSubroutineEvent targetDescriptor:target returnID:kAutoGenerateReturnID transactionID:kAnyTransactionID];
[event setParamDescriptor:function forKeyword:keyASSubroutineName];
[event setParamDescriptor:parameters forKeyword:keyDirectObject];
parameters=nil;
function=nil;
return event;}

And this is the invocation:

NSUserAppleScriptTask *automationScriptTask = [self automationScriptTask];
if (automationScriptTask) {
    NSAppleEventDescriptor *event = [self commandEventDescriptor:@"terminal" withParams:@[@"date",@"time"]];
    [automationScriptTask executeWithAppleEvent:event completionHandler:^(NSAppleEventDescriptor *resultEventDescriptor, NSError *error) {
        if (! resultEventDescriptor) {
            NSLog(@"%s AppleScript task error = %@", __PRETTY_FUNCTION__, error);
        }
        else {
            
        }
    }];
}

My expectation is to obtain some like this in Terminal:

macbook:~ xxx$ who

macbook:~ xxx$ date

macbook:~ xxx$ time

Instead I have:

macbook :xxx$ who

macbook :xxx$ d

-bash: d: command not found

macbook :xxx$ a

-bash: a: command not found

macbook :xxx$ t

-bash: t: command not found

macbook :xxx$ e

-bash: e: command not found

Simply put: I want to pass to Applescript array of two values ("date" and "time") but the script receives only one (first) value. Iteration on params gives me 'd','a','t','e' only.

So where did I go wrong?

4
  • Expecting broken commands to behave a certain way will likely result in unexpected results... >> 123 is not a valid command, so the ride is over there. if that's not what you expect then start by trying something valid. Commented Dec 29, 2015 at 21:24
  • I brought an example with valid command Commented Dec 29, 2015 at 21:34
  • 1
    For a sandboxed app the recommended way is NSAppleScriptTask accessing application related scripts in ~/Library/Application Scripts or AppleScriptObjC with an ObjC bridge class. Commented Dec 29, 2015 at 21:47
  • sorry to say, but this notice is both correct and useless Commented Dec 30, 2015 at 17:12

1 Answer 1

2

I think I have found the answer. Being not entirely sure whether it is the correct and canonic answer, but it seems to be in right direction. Anyway, my understanding of the problem is that aforementioned script accepts only one argument. I provided two arguments. Thus the script politely ignored the second argument. My solution was to pack both arguments into one descriptor and then serve it as single argument. Being more specific - here is the relevant code:

- (NSAppleEventDescriptor *)commandEventDescriptor:(NSString*) command withParams:(NSArray*)inputParams{
NSUInteger c=1;
NSAppleEventDescriptor *parameters = [NSAppleEventDescriptor listDescriptor];
for (NSString* s in inputParams) {
    NSAppleEventDescriptor *parameter = [NSAppleEventDescriptor descriptorWithString:s];
    //indexing starts from 1, NOT 0
    [parameters insertDescriptor:parameter atIndex:c];
    parameter=nil;
    c++;
}
// parameter

// target
ProcessSerialNumber psn = {0, kCurrentProcess};
NSAppleEventDescriptor *target = [NSAppleEventDescriptor descriptorWithDescriptorType:typeProcessSerialNumber bytes:&psn length:sizeof(ProcessSerialNumber)];

// function
NSAppleEventDescriptor *function = [NSAppleEventDescriptor descriptorWithString:command];

// event
NSAppleEventDescriptor *event = [NSAppleEventDescriptor appleEventWithEventClass:kASAppleScriptSuite eventID:kASSubroutineEvent targetDescriptor:target returnID:kAutoGenerateReturnID transactionID:kAnyTransactionID];
[event setParamDescriptor:function forKeyword:keyASSubroutineName];

//packing the pair of arguments into one Event Descriptor
NSAppleEventDescriptor* l0=[NSAppleEventDescriptor listDescriptor];
[l0 insertDescriptor:parameters atIndex:1];

[event setParamDescriptor:l0 forKeyword:keyDirectObject];
parameters=nil;
function=nil;
return event;}

Now the script behaves as expected - opens terminal window, runs command "who", then command "date", then command "time".

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.