Quit app that may not even be installed

I need to be able to tell an application with a particular name to quit. Here’s the catch… it may not even be installed! In that case, just the mere mention of the app in my AppleScript causes AppleScript Editor to hassle me constantly about where it is. I can’t have that happen to the user! (The target audience of this script is folks who won’t understand what they’re being asked.)

How can I tell an application to quit without this happening?

Here’s my current code:

on ApplicationIsRunning(appName)
	tell application "System Events" to set appNameIsRunning to exists (processes where name is appName)
	return appNameIsRunning
end ApplicationIsRunning

	if ApplicationIsRunning("Genieo") then
		tell application "Genieo" to quit
	end if
	if ApplicationIsRunning("Application") then
		tell application "Application" to quit
	end if

This might work:

on ApplicationIsRunning(appName)
	tell application "System Events" to set listApps to name of processes
	if listApps contains appName then return true
	return false
end ApplicationIsRunning
set appName to "Genieo"

if ApplicationIsRunning(appName) then
	using terms from application "System Events"
		tell application appName to quit
	end using terms from
end if

on ApplicationIsRunning(appName)
	tell application "System Events" to set appNameIsRunning to exists (processes where name is appName)
	return appNameIsRunning
end ApplicationIsRunning

The problem why ScriptEditor is constantly asking where application Genieo is is because it’s for checking it’s syntax and compiling the code. When you wrap a using terms from around some piece of code the dictionary is loaded from that application and can be used for another application.

Perfect! That allows the code to compile and run without the request.

Thanks a bunch!

Okay, maybe the problem is not entirely solved. I found that one of those apps (the one named “Application”) stubbornly refused to respond, probably because it’s just a small Unix process hidden away out of sight (I guess?), so I just put in a shell script to call killall.

However, now I’m trying to use the same trick to quit any browsers that might be open:

if ApplicationIsRunning("Safari") then
	tell application "Safari" to quit
end if
if ApplicationIsRunning("Google Chrome") then
	using terms from application "System Events"
		tell application "Google Chrome" to quit
	end using terms from
end if
if ApplicationIsRunning("Firefox") then
	using terms from application "System Events"
		tell application "Firefox" to quit
	end using terms from
end if

The problem is, when I open this script, it immediately opens Safari and Firefox (strangely, not Chrome, which is also installed). It doesn’t seem to care about the “using terms from” bit… it opens the apps regardless. Is there a way to do this properly, without opening the apps if they’re not open? Or do I just need to killall them all?

In my first example I’m using tell application variable, now you’re using static strings again. Then it will open the applications again. Like in my first example you need using terms of and put the application string in a variable.

edit: Also be aware that the process names in System Events doesn’t need to match the application’s name in AppleScript.

repeat with appName in {"Safari", "Google Chrome", "FireFox", "Opera"} --please check these names 
	set targetApplication to contents of appName
	if ApplicationIsRunning(targetApplication) then
		using terms from application "System Events"
			tell application targetApplication to quit
		end using terms from
	end if
end repeat

Ahh, so the key is the static strings, as opposed to putting the name in a variable. Just tried that, and it works. That’s just plain weird… why does static vs in a variable make a difference? Is there some logical reason, or is this just another of those weird little AppleScript things?

It’s not weird. When AppleScript is compiled all the commands are turned into AppleEvents. During compilation, the creation of an AppleEvent is based on the dictionary file of the target application. It will look at it’s syntax, look the key words op in the dictionary and create an event based on dictionary values. When using a using terms from application block it will read another dictionary. However I can create events that will malfunction because not all the events for System Events applications will work for browsers.

Then when I’m inside an dynamic tell application block I want to be able to target another static application like the Finder. When using terms from application block would work on all the code it contains, how would I target an second application in that block? Even inside an using terms from application block a tell application “appname” will use the dictionary of application appname and sets it’s target to that application.

It’s not werid, nor a bug but a very nice way of having a dynamic target application in your target path.