How do I create an AppleScript file using NSAppleScript? - cocoa

My code looks like this:
NSMutableString* cmd = [NSMutableString new];
[cmd appendString:#"script createScriptFile\n"];
[cmd appendString:#"beep\n"];
[cmd appendString:#"end script\n"];
[cmd appendString:#"store script createScriptFile in \"/tmp/narg.scpt\"\n"];
NSAppleScript* script = [[NSAppleScript alloc] initWithSource:cmd];
NSDictionary* err = nil;
NSAppleEventDescriptor *result = [script executeAndReturnError:&err];
which runs fine without errors, but the resulting script file (narg.scpt) looks like this:
script createScriptFile
beep
end script
store script createScriptFile in "/tmp/narg.scpt"
and what I want is for narg.sctp to look like this:
beep
What am I doing wrong?
Thanks,
Chris

Related

How to execute cd commands with apple script

I have written a program to execute the commands in cocoapp using apple script. There are 2 issues am facing
1) the applescript is exceuting always from the projet directory not from the root
2)cd command is working , but when i do pwd it shows the previous directory name not the new one.
+(BOOL)callAppleScriptForScriptFile:(NSString *)command{
BOOL isError = YES;
NSAppleEventDescriptor* returnDescriptor = NULL;
NSDictionary* errorDict = nil;
NSString *appleScriptCommand = [NSString stringWithFormat:#"do shell script \" %# &> /Users/username/Desktop/.output.txt\" user name \"username\" password \"password\" with administrator privileges",command];
//NSLog(#"Script command %#",appleScriptCommand);
NSAppleScript* scriptObject = [[NSAppleScript alloc] initWithSource:appleScriptCommand];
returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
if (errorDict != NULL){
NSLog(#"%#",errorDict);
isError = NO;
}
DescType descriptorType = [returnDescriptor descriptorType];
NSLog(#"descriptorType == %#", NSFileTypeForHFSTypeCode(descriptorType));
NSData *data = [returnDescriptor data];
double currentPosition = 0;
[data getBytes:&currentPosition length:[data length]];
NSLog(#"currentPosition == %f", currentPosition);
[self readFromFileAndSend];
return isError;
}
Expecting output like this
cd Desktop
o/p: sucess(no need to print)
pwd
o/p: Desktop
Each do shell script statement uses a new shell process, so you can't do something like change the working directory in one statement and then expect it to be the same in another. For example, if you use the separate statements
do shell script "cd ~/Desktop"
do shell script "pwd"
the second statement will show the root directory, because it is starting over - it doesn’t have anything to do with the first statement. You need to include all the commands in the same statement
do shell script "cd ~/Desktop; pwd"
From a Cocoa application, you can also use NSTask, which would avoid all the Apple Event stuff.

Shell script with NSTask doesn't work

I have a command (xcodebuild) that if I try in terminal it works very well. When I try to put it on my code:
let xcodeProjectPath = "/Users/xxx/Desktop/Code/xxx.xcworkspace"
let xcodeArchivePath = "/Users/xxx/Desktop/xxx.xcarchive"
let schemeName = "XXX"
let pid = NSProcessInfo.processInfo().processIdentifier
let pipe: NSPipe = NSPipe()
let file: NSFileHandle = pipe.fileHandleForReading
let archiveCommand = "xcodebuild -scheme \(schemeName) -workspace \(xcodeProjectPath) -configuration Release -archivePath \(xcodeArchivePath) archive"
let task = NSTask()
task.launchPath = "/bin/sh"
task.arguments = NSArray(objects: "-l", "/Users/xxx/Desktop/test.sh") as [AnyObject]
task.standardInput = NSPipe()
task.standardOutput = pipe
task.launch()
let data = file.readDataToEndOfFile()
file.closeFile()
let grepOutput = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Returned: \(grepOutput!)")
It doesn't work and return me:
** ARCHIVE FAILED **
The following build commands failed:
DataModelVersionCompile /Users/xxx/Library/Developer/Xcode/DerivedData/XXX-fbrisxgdcevajabbkhkejvwjrxyt/Build/Intermediates/ArchiveIntermediates/XXX/InstallationBuildProductsLocation/Applications/XXX.app/Database.momd Application/Resources/Database/Database.xcdatamodeld
My script.sh is:
#!/bin/sh
xcodebuild -scheme XXX -workspace /Users/xxx/Desktop/Codice/xxx.xcworkspace -configuration Release -archivePath /Users/xxx/Desktop/provaBuild.xcarchive archive
Any idea? :(
After many attempts I discover that if I try my code running app with Xcode it doesn't works. If i build the mac app... everything works!
What you are trying to accomplish?
You archiveCommand variable is never used and the second NSTask is initialized with an external sh file.
Anyway I think you are trying to read the pipe before the operation ends; I think waitUntilExit method just before launch command should help (or at least use the termination handler).
This is a test code with the relevant part of your question; it should works fine (I've written it in ObjC but the translation is very straightforward).
NSArray *args = #[ #"-scheme",schemePath,#"-workspace",prjPath,#"-configuration",#"Release",#"-archivePath",archPath,#"archive"];
[task setArguments:args];
NSPipe *outputPipe = [NSPipe pipe];
[task setStandardOutput:outputPipe];
[task setTerminationHandler:^(NSTask *task) {
NSFileHandle * read = [outputPipe fileHandleForReading];
NSData * dataRead = [read readDataToEndOfFile];
NSString * stringRead = [[NSString alloc] initWithData:dataRead encoding:NSUTF8StringEncoding];
NSLog(#"output: %#", stringRead);
}];
[task launch];

NSProcessInfo returns different PATH than "echo $PATH"

I am trying to programatically figure out whether there is a specific binary in the system PATH. To get the environment I used both
NSString* path = [[[NSProcessInfo processInfo] environment] objectForKey:#"PATH"];
and
NSString* path2 = [NSString stringWithUTF8String: getenv("PATH")];
both yielding the same result, in both cases different then echo $PATH in console. Both path and path2 does not contain paths set via /etc/paths.d, so the question is how to get the the environment PATH as returned from console programatically?
NSProcessInfo will just access information about current process. For example below i am executing the same echo $PATH command in cocoa and am getting the same output which NSProcessInfo is displaying. So in the terminal when you execute the same command. You will get different ouput. Because it is showing the path of current process in terminal. If you want to see the same output of both you can execute this command in terminal launchctl getenv PATH which will be equivalent to [[[NSProcessInfo processInfo] environment] objectForKey:#"PATH"];
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: #"/bin/bash"];
[task setArguments:[NSArray arrayWithObjects: #"-c", #"echo $PATH",nil]];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
NSData *data;
data = [file readDataToEndOfFile];
NSString *response = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog(#"%#",response);

How to predefine Apple Script constants or variables

Is it possible to predefine constant or variable for an AppleScript in cocoa application?
in other words is the function "addConstantToAppleScript" (used in the following code) definable?
addConstantToAppleScript("myText", "Hello!");
char *src = "display dialog myText";
NSString *scriptSource = [NSString stringWithCString:src];
NSAppleScript *appleScript = [[NSAppleScript alloc] initWithSource:scriptSource];
NSDictionary *scriptError = [[NSDictionary alloc] init];
[appleScript executeAndReturnError:scriptError];
thanks.
If you want to prepend an NSDictionary of key/value pairs to the beginning of an NSString containing AppleScript you could use something like the following function. Personally I would do this as a category on NSString but you have asked for a function.
NSString *addConstantsToAppleScript(NSString *script, NSDictionary *constants) {
NSMutableString *constantsScript = [NSMutableString string];
for(NSString *name in constants) {
[constantsScript appendFormat:#"set %# to \"%#\"\n", name, [constants objectForKey:name]];
}
return [NSString stringWithFormat:#"%#%#", constantsScript, script];
}
This function converts the key/value pairs to AppleScript statements of the form set <key> to "<value>". These statements are then added to the front of the supplied script string. The resulting script string is then returned.
You would use the above function as follows:
// Create a dictionary with two entries:
// myText = Hello\rWorld!
// Foo = Bar
NSDictionary *constants = [[NSDictionary alloc ] initWithObjectsAndKeys:#"Hello\rWorld!", #"myText", #"Bar", #"Foo", nil];
// The AppleScript to have the constants prepended to
NSString *script = #"tell application \"Finder\" to display dialog myText";
// Add the constants to the beginning of the script
NSString *sourceScript = addConstantsToAppleScript(script, constants);
// sourceScript now equals
// set Foo to "Bar"
// set myText to "Hello\rWorld!"
// tell application "Finder" to display dialog myText
NSAppleScript *appleScript = [[NSAppleScript alloc] initWithSource:sourceScript];

Applescript and Cocoa

I would like to call a IBAction within a cocoa app from applescript:
I want to call:
- (IBAction)reverse:(id)pId;
{
direction = -1;
}
with a line in an external applescript file like:
tell application "theapp"
reverse
end tell
Any Ideas?
Thanks in Advance
Use NSAppleScript.
NSAppleScript *as = [[NSAppleScript alloc] initWithSource:#"tell application \"theapp\"\nreverse\nend tell"];
NSDictionary *err = nil;
NSAppleEventDescriptor *desc = [as executeAndReturnError:&err];
NSLog(#"Error: %#\nData: %#", err, desc.data);
[as release];
There is also a good answer about Scripting Bridge here

Resources