run script with parameters

Hi, hope someone out there knows the answer to this one…

I am trying to run an Applescript from within a different applescript:

set filespath_01 to xxxxxxxxx:xxxxxxx:xxxxxxxxxxx:"
set x & "mysecondscript.scpt" as alias
try
	run script (x) with parameters {1, 2}
on error
	say "error"
end try

this works ok! but I cant make the parameter property to work… how to I get the parameters once I am ollready in my second script:

This is the second script:

Set w to get script parameters
display dialog w

this does not work! pleas help!

Brian

Save this as myScript.scpt on your Desktop


on run {A, B}
	display dialog A & space & B buttons {"OK"} default button "OK"
end run

Run this script as an example:

set xxx to (path to desktop as text) & "myScript.scpt" as alias
run script xxx with parameters {"one", "two"}

Works perfect!! thank you very much!!!

:slight_smile:

just one more question that I think you know the answer to… how to get a value back to the master script? is this possible?

Save this as myScript.scpt on your Desktop

on run {A, B}
	set C to A + 3
	set D to B + 4
	return {C, D}
end run

Run this script as an example:

set xxx to (path to desktop as text) & "myScript.scpt" as alias
set theResult to run script xxx with parameters {1, 2}

Hello!

Since parametes are a way to send and receive values between scripts, I see it relevant to mention the other way, by using globals, though properties is a better way really.

I have been infatuated by globals for a while now, and I have done some observations:

An undeclared global, can be viewed as a private global, (it is still global, but in the sense, that it gets the context saved an all that, and can be used to “configure” script objects as it is a “free” variable.)

A global that isn’t necessarily declared at toplevel, but declared as global somewhere in a handler, will work inside the current script-file and in any loaded script objects, provided the global are declared global before the script is run. The global doesn’t need to be declared by the loaded script objects. But it needs to be declared in any handlers. in the file were it were declared, but not in any subsequently loaded script objects run handlers.

I hope this makes sense.

Can you give an example of how to pass values between scripts by using globals (and not parameters) and explain why that is a better way?

Are you talking about storing data in script objects?

-- Save the Data
set thePath to (path to desktop as text) & "myData.scpt"
script myPrefs
	property favoriteColor : "blue"
	property favoriteColor2 : "yellow"
end script
store script myPrefs in file thePath replacing yes

-- Read the Data
set thePath to (path to desktop as text) & "myData.scpt"
set xxx to (load script file thePath)
-- or --
set xxx to favoriteColor of (load script file thePath) 

I am not saying it is a better way, just a different way. (And properties are best for storing values.)

But it may be a more convenient way, if you have a small set of scripts that are designed to work together.

I basically came forward with it as an alternative to parameters. The pros for using globals is that you then can run your script independtly whether the global are set or not, as you can catch this in a try - error block, this is not so easy with parameters specified. So your script objects then becomes more flexible.

The cons with globals, is that the communication sort of becomes undocumented, but it is easy to remedy that with some comments. And practically speaking, most of what we do with AppleScripts are side effects anyway, and most of our scripts stays on our private machines.

Using properties for passing values back and forth, is also a great way to do it. There is one thing to be alert of then, and that is to not set the property to the value of a global, implicit, (maybe explicitly declared also), as it may “freeze” the script to that value. That is, making a “closure”. I allways use locals to set properties in other script objects with.

Things to consider.:slight_smile:

Thank you!!! :smiley:

I’m using ‘run script with parameters’ when I will run a script with OSAScript. This way I’m able to send string arguments over the command line into another script. Quite usefull when a script needs to run in the background.

For instance this script:

on run argv
	set {firstArgument, secondArgument} to argv
	tell application "Finder" to display dialog secondArgument
end run

I saved it on my desktop and named it “script1.scpt”. When I want to call this on the command line and put it in the background so the main script doesn’t wait:

set s to quoted form of POSIX path of ((path to desktop folder as text) & "script1.scpt")
do shell script "osascript " & s & " 'hello world!' 'Goodbye' &> /dev/null &"

more about backgrounding script can be found here

Absolutely, parameters have their purpose, also for mere script objects. Especially for osascripts, and you can put rather large osascripts in shell scripts too, using heredocuments, and parameterpassing for feeding it with values from the commandline!

Here is a way to see to that the osascript’s parameters keep their quotes (so that spaces in filenames will work for instance), by using $@, the script as such is made by Nigel Garvey.

[code]#!/bin/bash
osascript <<END! - “$@”
on run {pathToPDF, pageNum}
set pdfFile to pathToPDF as POSIX file
tell application “Preview” to open pdfFile

tell application "System Events"
	tell application process "Preview"
		set frontmost to true
		-- Execute an option-command-"g" keystroke to get the "Go to page." dialog.
		keystroke "g" using {option down, command down}
		-- The dialog's a sheet in Preview 5.0.3. Wait for it to appear.
		repeat until sheet 1 of window 1 exists
			delay 0.2
		end repeat
		-- "Type in" the page number and press Return.
		keystroke pageNum
		keystroke return
	end tell
end tell

end run
END![/code]

It’s not possible for a script in one file to access or share another’s globals.

From the point-of-view of parameter passing, a script should ideally have no idea of another script’s variables, only what sort of parameters it expects and what sort of result it returns.

I think I have made myself unclear.

The premise is that the other script in the other file is loaded and run from the first one, then it can read and set the global variable in the first script.

It is not a good practice, but sometimes convenient. :slight_smile:

An example to clearify:

It works when the global is used in the run handler implicit or explicit in the called script, because of the shared address space, when there is no script object enveloping the run handler in that script.

Calling script:



script myscript
	on run
		myfirsthandler()
		myhandler()
	end run
	on myfirsthandler()
		global myvar
		set myvar to 5
	end myfirsthandler
	on myhandler()
		global myvar
		log myvar
	end myhandler
	
end script

log "new run"

tell myscript to run

set mscr to load script ((path to temporary items from user domain as text) & "myotherscript.scpt") as alias
tell mscr to run
log myvar

The script that is called:


on run
	log "otherscript " & myvar
	set myvar to 6
	# thehandler()
end run

on thehandler()
	log "otherscript's handler " & myvar
end thehandler

Log:

(new run)
(5)
(otherscript 5)
(6)

I understood what you meant. As I said, neither script can access the other’s globals.

It would be a very bad practice, even if it worked, because the called script could potentially interfere with the calling script, which is even more outrageous than the other way round.

Edit: OK. I’ve just seen your later post and will try to work out why your example works when my own test scripts didn’t. It’s still bad practice though.

The worst thing about it, I think, is that if the first calling script is called with a script runner that saves the state, then the state of the called script is saved as well.

But say, if you develop an app, and you have lots of scripts that are called from the main script they are all dedicated to work with eachother, then this technique may be more convenient than both properties (best practice when not using parameters), or parameters.

Ducks…:slight_smile:

The reason turns out to be that you’re using ‘run’ to run the loaded script, whereas I was using '‘run script’.

Hello!

I think that is a part of it, the way I do it, they becomes part of the environment, with the load script. Because I thought I really exploited the Shared environment thing:

If you have two properties with the same name at the top level of two scripts, (outside any script-objects), then I think those two properties will become the same one, or at least sharing the same value. When one of the scripts are loaded, and run from the other.

That is why I always envelop my scripts in script objects, when such effects aren’t sought for.(Which is a good practice.)

Now, learning that run script avoids this was new to me! :slight_smile:

As was the fact that ‘run’ doesn’t to me. It’s useful to know about such possible pitfalls.

Sometimes a bug, sometimes a feature.

I think It is cool to know that you can have “universal” variables.

But, in most cases the shared scripting environment poses as a bug. Like when you for instance link scriplibraries into scripts with Script Debugger. Then, if you load, then run a script from within another, you get at best a warning about the conflict. Run script avoids this since a brand new scripting environment is created… Run script must also be faster than the two combined statements. Though I am not sure what is worst, creating a totally new scripting environment, or adopting to the one that is already there.

One thing is sure, when for some reason either the current scripting environment is “littered”, or there are too much to take into account in it, like if you have and applet, or run a script from the script menu, then it speeds the process considerably by running the script. I think either ways are good here, using run script, or load it, or just tell it to run if it is present in the script file. I tend to use the latter construct with success.

Now, if the same property are declared in the top level of a script, and that property holds a scriptobject, then I think the library becomes shared, so that you end up with just one instance, and a slightly lower memory imprint during that particular execution, that way the bug is a feature, as long as your libraries are definitively static, and doesn’t save any values from the running script. Libraries - not Script Objects that does a task and saves some values, if you understand what I mean.

As far as I have figured it, the only way to evaluate stuff into records and such is by the run script statement.

I think I am all done with the subject by now. I do agree that in most cases it is a pitfall, but at the same time, it is one of those “dirty” “dirty” things that makes AppleScript so intriguing.

Edit The best thing about this, is that I then can have a script call a script call a script, without having to be concerned about the shared propertynames, that should presumably call the same library. Now, there is a conflict there, if the library has been updated between the differerent scripts I guess. So, making it all work this way will make me have to build dependencies as I update libraries. Which is a big pitfall to the scheme really.

But . if I assigned the script libraries to globals, so that they would load each and everytime, it would sure impede speed penalties, but I would always load fresh code, and my script could coexist with others in a call chain, and be executed independently! :wink: