Can I make AppleScript perform an action when I quit an app?

Howdy!

I’ve created a couple of neat scripts for Myth III and WarCraft III. Basically, when I launch a script for a game, it opens its disk image, goes to the folder of the game, opens the game application, and then closes the window of the game folder. This is great, but when I quit the game, I have to manually eject the disk. This is not a big deal, of course, but I would love to add some code to have the Finder eject the disk when I quit the game.

Basically, what I want to do with the script is:

  1. Go to folder of game/disk image
  2. Open the disk image
  3. Open the game application
  4. Close the Finder window of the game
  5. Play game
  6. Quit the game and have the same script eject the disk image

1-5 are not a problem. :slight_smile:

I’m by far from an expert as can be perceived. I’ve used AppleScript very, very few times, so please, if you could possibly just give me a line or two of code to try, this would be very much appreciated.

One other question: how come the ‘record’ function doesn’t work in OS X’s Script Editor? It works fine in OS 9 but not in OS X.

  • Matt

I guess what I would see as being a solution would be to have your script launch another script that watches to see if the game is running…

  1. Go to folder of game/disk image
  2. Open the disk image
  3. Open the game application
  4. Close the Finder window of the game
  5. Play game
  6. Launch second “watcher” script

“watcher” script

  1. During idle check for game
  2. if game isn’t running
    eject disk
    quit
    end if

Thanks for your response!

Like I said, I am very ignorant when it comes to AppleScript. I tried writing what you said, but it doesn’t appear to be in proper format. If at all possible, could someone write an example script to show me how the code should be setup?

This is a sample. You can save it as stay-open app.

global check_for

on run
     set check_for to "WarCraft III"
end run

on idle
     tell application "Finder" to name of processes --> name of running apps
     if check_for is not in contents of result then
          --> do whatever
     end if
     return 15 --> check every 15 seconds
end idle
global check_for

on run
	set check_for to "WarCraft III"
end run

on idle
	tell application "Finder" to name of processes --> name of running apps 
	if check_for is not in contents of result then
		eject "Warcraft III"
		--> do whatever 
	end if
	return 15 --> check every 15 seconds 
end idle

AppleScript tells me that it expected and ‘end of line’ but got a ", thus cannot compile the code. What should I do?

That error points to your line “eject”. This command is a Finder command… So, to execute it, you must enclose it into a tell block:

tell application "Finder"
     eject disk "Warcraft III"
end tell

--> or, in a single line:

tell application "Finder" to eject disk "Warcraft III"

Note the word “disk” after “eject”.
“Warcraft III” doesn’t mean nothing to the Finder. But «disk “Warcraft III”» is an object, and the Finder know what to do with it…

Good luck!

Great! That worked beautifully. Now the final touch is to have the eject script quit after it’s ejected the disk. I tried adding the line “tell application “eject script app” to quit”, but it tells me to locate the application to read its dictionary. What’s the last touch here?

tell me to quit

You can refer to applications using possesives. So, the app running the script is me.

tell application "Finder"
	version --> finder, 10.2.1
	its version --> finder, 10.2.1
	my version --> applescript, 1.9.1
end tell

Dang it, I screwed up. Let me explain.

I pretty much got everything working except for one error. I came here to post about the error (which I’ll get to momentarily) and started to paste both scripts/apps that I’ve made with your help. Upon pasting the codes, I noticed that the script for ejecting the disk was missing the ‘tell me to quit’ line. Now I am relatively sure that I must have been working on a copy of that script and accidently deleted that file. I saved a run-only application and now can’t recover the code from the ‘good’ application. Here’s what I thought I had did, but it’s producing different results than the run-only application, so it’s different somehow:


global check_for

on run
	set check_for to "Warcraft III"
end run

on idle
	tell application "Finder" to name of processes --> name of running apps 
	if check_for is not in contents of result then
		tell application "Finder" to eject disk "Warcraft III"
		tell me to quit
		--> do whatever 
	end if
	return 15 --> check every 15 seconds 
end idle

Now the first, run-only app that I can’t get the code for produces this error after I quit the game:

When I press OK, the program ejects the disk and quits. Everything is great except for that error. However, I don’t know how this code is different from the one above, which produces a different error:

Pressing OK for this error does not quit the application or eject the disk. Bad stuff. But I have the code for this one.

Dang, I’m stuck. If you’ve got any tips, please give 'em. :slight_smile:

This is hard to explain, and I can understand that someone may be confused by the post above. Here’s a summary.

Run-only app

  • The app works very well except for an error; when I press OK, it ejects the disk and quits itself.
  • I don’t have the code for it.

An attempt of reproducing the run-only app

  • The app doesn’t work how I want. I get an error, the disk stays mounted, and the program doesn’t quit itself.
  • I have the code for it.

You don’t need save this script run-only, but only “stay-open”. About “can’t get «class cdis»…”, means that it does not exists a disk called “Warcraft III” mounted in your desktop.
Note that “check_for” (“Warcraft III”) is the name of the app as you can see it at the dock. And “eject disk” may complain the name of the disk you wish eject. Have both the same name?
About your second error, seems a corruption error. You may trash all your versions and build a new one with the code above. Check that “Warcraft III” is the name of the app (variable check_for), and that “Warcraft III” is too the name of the disk to eject. Save as application-stay open, and it should be done!

This makes sense. I guess the error shows up because of the location of the ‘launch Eject Warcraft III’ command. The code has to be placed where it is becuase if the Eject application launches after the disk image mounts, then it will eject the disk before Warcraft III launches. Doing this will cause Warcraft III to keep asking me to insert the CD becuse the disk image will have already been ejected. I think the solution here is to delay when the ‘Eject Warcraft III’ script actually begins checking. Can I somehow set the script to start about thirty seconds or so after it is launched?

They both share the exact same name, including spacing. I can’t really rename the disk (image) because that’s what the Warcraft III application looks for when it’s checking for the CD.

Correct! Spot-on.

on run
     delay 30
     --...

That was straight-forward enough. :slight_smile:

Thanks a ton for your help; everything is behaving exacly how I wanted.

The only strange thing was that saving the Launch applications as normal (not run-only) was strange. When I ran these apps, they would always start Classic. I would save in new documents, thinking perhaps something got corrupt, but it always repeated. When I saved these applications as run-only, however, Classic didn’t startup.

Really, thanks a lot for all of your help. I’m very grateful.

Look at your save dialog, and check that “requires classic” is unchecked.
If it is, then perhaps the script is trying to launch classic Finder…

Try changing:

tell app "Finder" to...

to

tell app "Finder.app" to...

If it still doesn’t work, then you may tray change:

tell app "Finder" to...

to

tell app "Path:to:Finder.app" to...

(usually located at “diskname/system/library/coreservices/finder.app”)
And it may allways launch OS X Finder…

You should add custom quit handler to achieve this:


global check_for

on run
	set check_for to "Warcraft III"
end run

on idle
	tell application "Finder" to name of processes --> name of running apps 
	if check_for is not in contents of result then
		tell application "Finder" to eject disk "Warcraft III"
		quit {} of me
	end if
	return 15 --> check every 15 seconds 
end idle

on quit {}
	-- do here your additional action
	continue quit
end quit