Basic Applescript commands for all applications

Is there any way to get the path to a running script? “path to me” only gives you the path to the app that runs the script. I want something like, if I do this

osascript foo.scpt

and assuming foo.scpt is in ~/temp, inside foo.scpt it knows it’s in ~/temp, no matter where I run it.

And foo.scpt could be run from any app, so no assumption on the running app is available either.

this thread at Apple

http://discussions.info.apple.com/WebX?14@117.0OO9agXBtGO.5@.599cee49

discussed a solution but it assumes the running app is Script Editor.

Any suggestion?

I’m not sure if it’ll work or not, but the shell maintains a system environment variable ‘PWD’ which tracks the current working directory. You can use the ‘system attribute’ command to retrieve environment variables, so it might work for you:

set currentDir to system attribute “PWD”

I don’t know if it’ll return the path of the app or the script, or nothing at all.

I’m not sure if I understand exactly, but will something like this work?

[This script was automatically tagged for color coded syntax by Script to Markup Code]

It will display the path of the script from where ever it is launched from. And it has to be saved as an application.

No it doesn’t work. In particular Apple says we should not rely on $PWD:

http://developer.apple.com/technotes/tn2002/tn2065.html#Section5

I’d like to see this works but it doesn’t. “path to me” gives you the path to the app that runs the script (as discussed in the thread in Apple’s discussion forum as I cited above).

Unless the script is an application, I think you are out of luck. This, from a post to the applescript-users list on 03 November 2003, pretty much says it all:

– Rob

Ah, this is a bad news. But thank you for sharing this!

But I’m intrigued by his comment “A clever developer could implement something on their own…” - anyone has any clue here? (I certainly don’t).

The reason I want this is I’d like to have my script to be freely “movable” - it should run whereever it’s dragged to (and inside this script there’re some other shell scripts being called, and they live in the same place as the applescript).

Well, there may be a couple of ways to kludge through this. If you create a script and save it as an application, you can create/assign a unique creator code to it. The path to the application can then be retrieved via the Finder with the following code (this will use Script Editor’s creator code to obtain its path):

tell application "Finder" to ¬
	set appPath to application file id "ToyS" as Unicode text

The actual script application would never need to run and it would be used only as an identifier/locator.

A similar method might be used if the script was distributed as a package. If the info.plist in the package contains a CFBundleSignature, the following could be used. (Check the info.plist in Script Editor’s package for an example.)

tell application "Finder" to ¬
	set appPath to application file id "com.apple.scripteditor" as Unicode text

I haven’t actually used either idea in a distributed script but I see no reason why they couldn’t be attempted. Of course, if there is more than one copy of the script installed, all bets are off.

– Rob (who might be totally wrong because he is under the influence of large quantities of cold medicine) :wink:

Any reason why your AppleScript can’t be compiled as an AppleScript Application?

Alternatively, have you considered using AppleScript Studio for this project? It’s a perfect platform for this kind of embedded shell script application as AppleScript Studio programs are packages and “path to me” yields a path to the package; all you have to do is append the constant/fixed path within the package to your shell scripts. Here’s an example of calling a function within another AppleScript (but you can use it as an example of how to set up a do shell script call):

tell (load script file (((path to me from user domain) as text) & "Contents:Resources:Scripts:ScriptName.scpt")) to functionCall()

If for some reason either of these two approaches won’t work for you, have you considered embedding the shell script in your AppleScript and making it part of your do shell script call? do shell script can handle a pretty large call, but this option would definitely be my last choice (due in large part to quoting issues).

Way too much cold medicine there Rob! If it is compiled as an Application, then “path to me” is sufficient.

By the way, for that cold, try Xlear. It’s amazing stuff. Also see: Beating Colds and Flu for some good tips. Good health!

Yeah, I was working on the assumption that the script was not an application. The assumption was based on this, in the first post: osascript foo.scpt

Thanks! I’ll check them out. <cough - hack - sniff> :wink:

Yes, but you said: “If you create a script and save it as an application…”

Oh, nevermind! Rob, you’re delirious, go back to bed! :wink:

Of course the $64 question is whether or not there is a reason why this script shouldn’t/can’t be saved as an application. If it can, clearly that’s the easiest solution to this problem. And personally i think AppleScript Studio would be the best way to go as all the files can managed as a project and the resulting “application” is really a package neatly containing all the files. But that could also be overkill, like using a sledge hammer to pound a finishing nail, so YMMV.

Maybe I’m missing something here, but isn’t the initial question, essentially, “How do I find out the path to a script loaded by another script?” How can you load a script without knowing its path? If you can load it, you’ve got to know where it resides, even if that is dynamic using something like “path to application support”. What am I missing?

Jon

The initial question was how the currently running script can find a path to itself. We cannot assume it was called by another script. Most likely it was called by an Application (e.g. System Events).

We have pretty much concluded that unless the running script is an Applet, path to me isn’t useful (i.e. it returns the path to the calling App). So the question has become (at least in my mind): Can the running script be an AppleScript application, or an AppleScript Studio package?

Given what the initial poster (fortepianissimo) has told us so far, it seems to me that might be a possiblity, and if so, most likely the best solution to the question at hand. fortepianissimo asked the question originally to solve the problem of how to call a shell script, which is in a fixed and known position relative to the currently executing script. The problem is that the location of the enclosing folder is variable and all that is certain is the location of the two scripts relative to each other. At least that is my understanding of the problem.

Thanks for the reply (and the links about flu too - although I’m almost close to getting done with it).

Ok so this particular script is for Mail.app’s rule action. I tried your suggestion: saving the script as an application, and do a “display dialog path to me as string” outside the tell app “Mail” block - it still shows the path to Mail.app…

As long as I can get the path to the script itself, not Mail.app, I’m happy… need more help!

Ah, this is all starting to make sense to me now!

I don’t know if this’ll work or not, but within the Applet, you might try something like: tell me to display dialog path to me as string

If that doesn’t work, then try this: Write a Mail.app AppleScript to call your Applet, so the Applet isn’t being invoked directly by Mail.app (i.e. you’ll have two AppleScripts; one is only there to call the other, which is an AppleScript Application).

If that doesn’t work, tell the Finder to start up the Applet (from the calling Mail.app AppleScript).

And if that doesn’t work, save the Applet as a “never closes” Applet, fire it up first, and then see what happens (it should work if it was running before Mail.app calls it).

Method 1 (tell me to display…): still points to Mail.app
The rest of the tips, except for the last one: but when you call the second applet, you already know the path to the applet right? So it’s probably not very useful…

The last one: Mail.app seems just ignore the rule - reasonable because the applet is already opened when the rule fires, so re-launching it fails.

Are we running out of possibilities here?

No. A statement like run application “MyApplet” is all that’s need (provided it is indeed saved as an Application).

Script Editor Example (which i have tested):
Create a new window with this code:

tell me to activate
display dialog "My path is:  " & (path to me as string)

and save as an application called “Quark”. You may close this window if you like; doesn’t matter.

Now create a new window with this code:

try
	run application "Quark"
end try

It calls the applet Quark, which displays a dialog with the path to itself. (Notice that if you execute Quark directly from the Script Editor, you get a different result: You get a path to the Script Editor.)

Well, you’re not re-launching; merely calling its run handler again, so it always should work. In Script Editor, if you save Quark as “stay open,” the example above still works, whether or not the application Quark is already running. However there are some nuances which may be coming into play here.

Some depend on whether or not the application is “stay open” or not, whether the application is running or not, etc. That’s why the “try” block is there in my example. I’m a bit rusty on all the details, but for the most part it has to do with Open vs Run handlers, and related issues. Something about when you run an app, there’s an implicit open, and so the code can get executed twice, or something like that.

I don’t recall the exact syntax offhand, but you should be able to call a named handler within the Applet to avoid some of these issues (by leaving the open and run handlers empty). But i don’t recall offhand how to form the call to a named script within an Applet like that, so that’s a whole other can of worms, and one that i’m not eager to open up.

AppleScript Studio makes it easy to call a named function, however, as i think it creates an AppleScript Dictionary for all named functions within the App. Have i said i think AppleScript Studio is the way to go on this project? :smiley:

Okay, so you can get along without it too, i suspect.

We’re almost there! This works when the caller is hooked to Mail via rule action (the path displayed is the path to the app - hallelujah). But 3 out of 4 times it gave death of beachball to Mail.app (had to force-quit it). My Mail setup has two accounts, and the only time when this didn’t happen was that only one account has a new message (so the dialog displaying path only showed up once). The other 3 times, the dialog showed up twice (one new message in each account), and then Mail.app hung.

As to using Applescript Studio project, I have one question: is it possible to call an ASS app from Mail.app rule action? I just tried choosing an ASS app as a rule action in Mail.app and nothing happened… (could be something else though)

Thanks again!

Well, i should warn you i’ve never scripted a Mail.app mail action. Did a lot of similar work with Claris eMailer, but that’s a different beast (and much more AppleScript friendly). All i have to offer are a few educated guesses.

You didn’t say if you were using the double AppleScript approach or not? Nor if you were using a stay-open Applet?

I suspect you could encounter problems if you call an Applet directly from Mail.app, so the double AppleScript approach may be required. That’s because Mail.app may be passing essential information to a script which would otherwise be lost if you call an Applet directly. Using a double AppleScript approach should get around any such problems. Then again, this may not be an issue, so YMMV.

As to why it appears to work sometimes, and “hang” other times… sounds like it could be either a timeout situation, a race condition, or something related to how the handlers are invoked. Again, it’s possible this may be resolved by the double AppleScript approach.

You should wait two or three minutes, as an experiment, before forcing a quit. If control comes back in that time, it’s a good bet it’s an AppleScript time-out situation.

Yes, it appears to allow you to choose an AppleScript Studio app, but i noticed it is also possible to choose other non-AppleScript app’s, like Clock and Chess (maybe it allows you to choose any Cocoa app?). My suspicion is you’ll need to use the double AppleScript approach when working with an AppleScript Studio app. In other words, i don’t think it’s fruitful to call the AppleScript Studio app directly from Mail.app.

It may be helpful to view the AppleScript Studio app merely as a wrapper around your shell script, rather than as an “AppleScript” per se. The “AppleScript code” is merely glue to invoke the shell script (which is tucked away within the app’s package). So the real AppleScript is the compiled AppleScript script invoked by the Mail Action (which calls the shell script’s wrapper application).

Hope this makes sense (and helps).