Calling an applescript with parameters

J

Jon Fogh

Hi I am experimenting with calling apple scripts from Java. I am using
the com.apple.cocoa classes.

I have this small Java program:

public class Test {

public static void main(String[] args) {

NSApplication.sharedApplication();

NSMutableDictionary error = new NSMutableDictionary();
String source = "";
source += "on run (mystr)\n";
source += "tell application \"Finder\"\n";
source += "display dialog \"Got a string: \" & mystr\n";
source += "end tell\n";
source += "end run\n";

NSAppleScript script = new NSAppleScript(source);
script.compile(error);
System.out.println("Error: " + error);

System.out.println("Is compiled: " + script.isCompiled());

NSAppleEventDescriptor desc =
NSAppleEventDescriptor.listDescriptor();
desc.insertDescriptor(NSAppleEventDescriptor.descriptorWithString("Hello
World"),0);
System.out.println("Desc: " + desc.stringValue());

script.executeAppleEvent(desc, error);
System.out.println("Error: " + error);
}

When running it, i get this:

Error: {}
Is compiled: true
Desc: Hello World
Error: {NSAppleScriptErrorNumber = -50; }

The ErrorNumber -50, indicates an error in the user parameter list. I
am not sure this i the right way to pass arguments to a compiled
applescript, but if it is, what is I doing wrong? If this isnt how to
do, how shouldt it be done?

Jon
 
D

David Phillip Oster

Hi I am experimenting with calling apple scripts from Java. I am using
the com.apple.cocoa classes.

You might take a look at my open source osasubr. It is in C++, but it will
show you the underlying system calls you can use.

<http://www.Turbozen.com/mac/osasubr/>

The problem is that on run doesn't take any parameters, but you can define
applescript subroutines that DO take parameters, and call them like so:

/* DoScriptRoutineHandle - given a handle that is a compiled list of
subroutines, execute the named subr,
passing it the string arguments. throws on errors. doesn't modify handle.
*/
std::string DoScriptRoutineHandle(const Handle h, const char *subrName, char * const argv[]){
StHandleLocker lock(h);
StAEDescriptor scriptDesc(typeOSAGenericStorage, *h, GetHandleSize(h));
StAEDescriptor subrEvent;
StAEDescriptor paramList;
StAEDescriptor reply;

UAppleEventsMgr::MakeAppleEvent(kASAppleScriptSuite, kASSubroutineEvent, subrEvent);
StScriptingComponent scriptingComponent(OpenDefaultComponent(kOSAComponentType,'scpt'));
ThrowIfOSStatus_(GetComponentInstanceError(scriptingComponent));
StOSAID scriptID(scriptingComponent, scriptDesc);
ThrowIfOSStatus_(AEPutParamPtr(subrEvent, keyASSubroutineName, typeChar, subrName, strlen(subrName)));
ThrowIfOSStatus_(AECreateList(NULL, 0, false, paramList));
for(char * const * p = argv; NULL != *p; ++p){
ThrowIfOSStatus_(AEPutPtr(paramList, 0, typeChar, *p, strlen(*p)));
}
ThrowIfOSStatus_(AEPutParamDesc(subrEvent, keyDirectObject, paramList));
ThrowIfOSStatus_(OSADoEvent(scriptingComponent, subrEvent, scriptID, kOSAModeAlwaysInteract, reply));
// if call returned OK, then ignore errors trying to write the result to stdout.
try{
StAEDescriptor aeResult(reply, keyAEResult, typeChar);
std::vector<char> buffer(UExtractFromAEDesc::AEGetDescDataSize(aeResult));
UExtractFromAEDesc::AEGetDescData(aeResult, &buffer[0], buffer.size());
std::string s(&buffer[0], buffer.size());
return s;
}catch(...){
}
return "";
}

/* DoScriptRoutine - looks for compiled script resource in the current resource file.
*/
std::string DoScriptRoutine(const char *subrName, char * const argv[]){
Handle h;

if(NULL == (h = Get1IndResource(kOSAScriptResourceType, 1))){
Throw_(resNotFound);
}
return DoScriptRoutineHandle(h, subrName, argv);
}

/* DoScriptFileRoutine - the meat of the program.
Under OS 9 and earlier, Script Editor put the compiled script into a resource. Under OS X,
Sript Editor puts the script into the data fork of the file. DoScriptFileRoutine
finds the script, and passes it on to the system calls.
DoScriptFileRoutine is exception safe: if anyhing throw, destructors clean things up.
*/
std::string DoScriptFileRoutine(const char *path, const char *subrName, char * const argv[]){
FSRef fsr;
Boolean isDir;
ThrowIfOSStatus_(FSPathMakeRef(reinterpret_cast<const UInt8*>(path), &fsr, &isDir));
if(isDir){
Throw_(-1);
}
Handle h;
StHandleBlock h1;
try{
StCurResFile save(FSOpenResFile(&fsr, fsRdPerm));
if(NULL == (h = Get1IndResource(kOSAScriptResourceType, 1))){
Throw_(resNotFound);
}
}catch(...){
FSSpec fs;
ThrowIfOSStatus_(FSRefMakeFSSpec(&fsr, &fs));
LFile file(fs);
file.OpenDataFork(fsRdPerm);
h = file.ReadDataFork();
h1.Adopt(h);
}
return DoScriptRoutineHandle(h, subrName, argv);
}


If you don't speak C++, the function calls inside the ThrowIfOSStatus_()s are
the system calls.
 
M

matt neuburg

David Phillip Oster said:
The problem is that on run doesn't take any parameters

Yes, it does. (Or it can, anyway. See my book for details.) Automator
actions rely upon this mechanism. m.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top