The goal is a script that empties certain Cache folders; for example, the Cache folder that Eudora uses, that Safari uses, etc. That is accomplished by placing aliases to those folders on my desktop and successively emptying them. This task is very straightforward.
What is not straightforward is to find what applications are open, applications which use those Cache folders because I need to first quit these apps before I empty the corresponding folders.
The glich happens with:
tell application thisAppName to quit
This would expand to, for example,
tell application “Eudora 6” to quit
since thisAppName contains the string “Eudora 6”.
This does not work, yet if I directly type:
tell application “Eudora 6” to quit
then, it works.
Here is the code:
set visible of every process whose visible is true and name is not "Finder" to false
set allAppFileList to (file of every application process whose file type is "APPL")
set allCacheAppNames to ¬
{"Eudora", "Explorer", "iPhoto", "Mozilla", "Netscape", "Safari"}
repeat with thisAppFile in allAppFileList
if thisAppFile is not (missing value as string) then
set thisAppInfo to info for thisAppFile
set thisAppName to name of thisAppInfo
repeat with eachCacheAppName in allCacheAppNames
if (thisAppName contains eachCacheAppName) then
-- for example, Eudora 6.app
-- strip ".app" suffix
set offset_dotapp to (offset of ".app" in thisAppName)
if offset_dotapp > 0 then set thisAppName to ¬
(text 1 thru (offset_dotapp - 1)) of thisAppName
-- for example, Eudora 6 -- and this does NOT work
tell application thisAppName to quit
end if
end repeat -- repeat with eachCacheAppName in allCacheAppNames
end if -- if eachAppFile is not (missing value as string) then
end repeat -- repeat with eachAppFile in allAppFileList
It’s not as complicated as that. When ‘telling’ an application, its path string at run time has the same effect as its name during compilation:
set allCacheAppNames to ¬
{"Eudora", "Explorer", "iPhoto", "Mozilla", "Netscape", "Safari"}
repeat with i from 1 to (count allCacheNames)
try
tell application "System Events"
set thisAppFile to (file of first application process whose name contains item i of allCacheNames)
end tell
tell application (thisAppFile as string) to quit
end try
end repeat
If you may have more than one version of any app open:
set allCacheAppNames to ¬
{"Eudora", "Explorer", "iPhoto", "Mozilla", "Netscape", "Safari"}
repeat with i from 1 to (count allCacheNames)
try
tell application "System Events"
set theseAppFiles to (file of every application process whose name contains item i of allCacheNames)
end tell
repeat with thisAppFile in theseAppFiles
tell application (thisAppFile as string) to quit
end repeat
end try
end repeat
set allCacheAppNames to ¬
{"Eudora", "Explorer", "iPhoto", "Mozilla", "Netscape", "Safari"}
repeat with i from 1 to (count allCacheAppNames)
try
tell application "System Events"
set thisAppFile to (file of first application process whose name contains item i of allCacheNames)
end tell
tell application (thisAppFile as string) to quit
end try
end repeat
And:
set allCacheAppNames to ¬
{"Eudora", "Explorer", "iPhoto", "Mozilla", "Netscape", "Safari"}
repeat with i from 1 to (count allCacheAppNames)
try
tell application "System Events"
set theseAppFiles to (file of every application process whose name contains item i of allCacheNames)
end tell
repeat with thisAppFile in theseAppFiles
tell application (thisAppFile as string) to quit
end repeat
end try
end repeat
repeat with i from 1 to (count allCacheAppNames)
try
tell application "System Events"
set thisAppFile to ¬
(file of first application process ¬
whose name contains item i of allCacheAppNames)
end tell
tell application (thisAppFile as string) to quit
end try
end repeat
=====
but Eudora, for example, remained open after script completion.
I still missed one of the miscopied variable names didn’t I?. Thanks for correcting it.
But do you mean “Eudora, for example, remained open” or “Eudora (only) remained open”? The script definitely works on my 10.2.8 machine, quitting every app I’ve named, or partially named, in the list - including Explorer and Safari - regardless of whether that app’s file is a file or a bundle. I don’t have Eudora, though, so I’m not able to test with it.
I suppose the next thing to try is to comment out the ‘try’ and ‘end try’ lines to see if trying to quit Eudora is throwing an error, and if so, what.
What if you just use the process names. This usually works for me unless you’re trying to quit some background application whose process has a different name.
set allCacheAppNames to ¬
{“Eudora”, “Explorer”, “iPhoto”, “Mozilla”, “Netscape”, “cSafari”}
tell application “System Events”
set visible of every process to true
set proc_names to (name of every process whose visible is true)
end tell
repeat with this_proc_name in proc_names
repeat with this_name in allCacheAppNames
if this_proc_name contains this_name then
tell application this_proc_name to quit
exit repeat
end if
end repeat
end repeat
I forgot that I changed Safari’s name because I’m using it right now.
Eudora, Safari, iPhoto – all of them still remain open.
Error that is thrown is similar to “Can’t get application ‘Eudora 6’”, with or without tell application “System Events” envelope, with or without try-end try envelope.
Just to keep it simple, changed line:
set allCacheAppNames to {“Eudora”}
By the way, I have 10.3.3 Panther
… and really important, thanks bunches for all your joint patience.
set all_cache_app_names to {"Eudora", "Internet Explorer", "iPhoto", "Mozilla", "Netscape", "Safari"}
repeat with one_app in all_cache_app_names
try
tell application "Finder" to set one_app to name of process (one_app as text)
tell application one_app to quit
end try
end repeat
The first line of the loop is just to test to see if we can do this. If we can’t, the process isn’t running and AppleScript will throw an exception (thus taking us out of the ‘try’ block and on to the next process name). If we can do the first line, we’ll stay in the try block and tell the process to quit.
-Colin Foster
(author of Quit Anything and guy who has spent FAR too much time figuring out how to systematically quit processes. )
Hmmm. It’s correctly identifying the process name. Maybe there’s a reference resolution problem in 10.3.3. If you’ve had no luck with anyone else’s suggestions, does this overkill make any difference?
set allCacheAppNames to {"Eudora", "Explorer", "iPhoto", "Mozilla", "Netscape", "Safari"}
repeat with i from 1 to (count allCacheAppNames)
set partialName to item i of allCacheAppNames
tell application "System Events"
set thisAppProcess to (first application process whose name contains partialName)
set thisAppName to (name of thisAppProcess) as string
end tell
tell application thisAppName to quit
end repeat
Or, without the two o’clock in the morning effect… :oops:
set allCacheAppNames to {"Eudora", "Explorer", "iPhoto", "Mozilla", "Netscape", "Safari"}
repeat with i from 1 to (count allCacheAppNames)
set partialName to item i of allCacheAppNames
try
tell application "System Events"
set thisAppProcess to (first application process whose name contains partialName)
set thisAppName to (name of thisAppProcess) as string
end tell
tell application thisAppName to quit
end try
end repeat
Unfortunately, neither Colin’s nor Nigel’s approach worked.
Trying to recap a bit,
the following does not work with the error ‘Can’t get application “Eudora 6”’
set thisAppName to “Eudora 6”
tell application thisAppName to quit
However,
tell application “Eudora 6” to quit
does work
=====
Next …
repeat with i from 1 to (count allCacheAppNames)
try
tell application "System Events"
set thisAppFile to ¬
(file of first application process ¬
whose name contains item i of allCacheAppNames)
end tell
display dialog thisAppFile as string
tell application (thisAppFile as string) to quit
end try
end repeat
displays the directory string followed by Eudora 6, with no script errors, but Eudora remains open.
=====
Next,
tell application "System Events"
set allAppFileList to ¬
(file of every application process ¬
whose file type is "APPL")
end tell
…
repeat with thisAppFile in allAppFileList
repeat with eachCacheAppName in allCacheAppNames
set thisAppName to name of thisAppFile
if (thisAppName contains eachCacheAppName) then
-- for example, Eudora 6.app
display dialog thisAppName
-- strip ".app" suffix
set offset_dotapp to (offset of ".app" in thisAppName)
if offset_dotapp > 0 then set thisAppName to ¬
(text 1 thru (offset_dotapp - 1)) of thisAppName
-- for example, Eudora 6
display dialog thisAppName
tell application (thisAppName as string) to quit
end if
end repeat -- repeat with eachCacheAppName in allCacheAppNames
end repeat -- repeat with eachAppFile in allAppFileList
This also does not work with the error “Can’t get application ‘Eudora 6’”
Even if I put the tell application statement before the stripping of “.app”, the error reads “Can’t get application ‘Eudora 6.app’”
By the way, the above results are ditto even without the tell application “System Events” envelope at the top.
I really remember my being very happy with OS 9 scripting … lots of additions out there made my life very easy.
What if you use the path to the bundle instead. See if this quits Eudora:
set the_app to choose file
tell application “Finder”
set ct to creator type of the_app
set app_path to (application file id ct) as string
end tell
tell application app_path to quit
–“CSOm”
I’m not sure if “CSOm” is the creator type for Eudora so used the choose file here.
or use the ‘application file’ property of application process:
tell application “Finder”
set the_app to item 1 of (every process whose name contains “eudora”)
set app_path to (application file of the_app) as string
end tell
tell application app_path to quit
When I use your ‘file of …’ method, I get the path to the application inside the bundle. Not sure what you get with Eudora but maybe you should check it out.
Oh dear. And you say this is true with other applications as well? It doesn’t make sense that the name should be acceptable when the script’s compiled but not when it’s run.
OK. Three last-ditch guesses at what might work, then I’m out of ideas…
-- Resolve 'application thisAppName' before telling it anything
set thisAppName to "Eudora 6"
tell (get application thisAppName) to quit
-- Ditto, with overkill
set thisAppName to "Eudora 6"
set thisApp to application thisAppName
tell thisApp to quit
-- Compile and run the quit line
set thisAppName to "Eudora 6"
run script ("tell application " & thisAppName & "" to quit")
Oh yes. And of course:
set thisAppName to "Eudora 6"
if thisAppName is "Eudora 6" then tell application "Eudora 6" to quit
I just downloaded and installed Eudora 6.1, which installs as just “Eudora” and changed its name to match what you must have: “Eudora 6”.
The problem is, it shows up in the Dock as “Eudora 6,” but its name is really just “Eudora.”
I launched Eudora 6, and also a (renamed) copy of TextEdit 13 and then ran the following script:
set all_cache_app_names to {"Eudora", "TextEdit"}
repeat with one_app in all_cache_app_names
try
tell application "Finder" to set one_app to name of process (one_app as text)
tell application one_app to quit
end try
end repeat
and both quit just fine. But if I used the names “Eudora 6” and “TextEdit 13” in the script (which is what the Dock tells me their names are) then the script fails to quit those processes.
So perhaps this is just a naming problem. Maybe you could try to run the following code once to get the real names of the apps you are having trouble quitting (while they are running of course). Then use the real name of the process in your list.
tell application "Finder"
name of every process
end tell
I guess another solution to this problem would just be to inline your quit statements instead of using a loop (since you mentioned it still worked when you used a constant instead of a variable):
try
tell application "Eudora 6" to quit
end try
try
tell application "Safari" to quit
end try
-- and so on
A slightly different approach… (works on 8.6)… substitute the appropriate creator types… (file id’s). It does not allow for the possibility of multiple app versions using the same creator.
–
tell application “Finder”
set app_names to {name of application file id “MSIE”, name of application file id “MOSS”}
set process_names to the name of every process whose file type is “APPL”
end tell
try
repeat with this_app in app_names
if this_app is in process_names then
tell application this_app
quit
end tell
end if
end repeat
on error
end try
–
(EDIT - After trying this on X, I conclude it won’t work… sorry.)
You can use the run script command from the Standard Additions to compile and run an AppleScript script on the fly.
on quitOthers(keepOpen)
tell application "System Events"
get application processes
end tell
repeat with myApp in result
set AppName to name of myApp
if AppName is not in keepOpen and AppName is not in systemProcesses then
run script "
try
tell application "" & AppName & "" to quit
end try"
end if
end repeat
end quitOthers
I used this to quit other applications in this script used to log out after the current song in iTunes finishes.
property maxWait : 10
property systemProcesses : {"loginwindow", "Dock", "SystemUIServer", "System Events"}
quitOthers({"iTunes"})
HideApp("iTunes")
endOfSong()
tell application "loginwindow"
ignoring application responses
«event aevtrlgo»
end ignoring
end tell
on endOfSong()
tell application "iTunes"
set myTrack to current track
set myFinish to finish of myTrack
set timeLeft to myFinish - player position
repeat while timeLeft > 0 and myTrack = current track
if timeLeft > maxWait then
delay maxWait
else
delay timeLeft
end if
set timeLeft to myFinish - player position
end repeat
end tell
end endOfSong
on quitOthers(keepOpen)
tell application "System Events"
get application processes
end tell
repeat with myApp in result
set AppName to name of myApp
if AppName is not in keepOpen and AppName is not in systemProcesses then
run script "try
tell application "" & AppName & "" to quit
end try"
end if
end repeat
end quitOthers
on HideApp(AppName)
tell application "System Events"
repeat with myProcess in processes
if (name of myProcess = AppName) then
set visible of myProcess to false
exit repeat
end if
end repeat
end tell
return
end HideApp
Thank you, thank you, thank you to all, especially the last individual who used run script “…”
– Empty All Cache = Delete contents of all Cache folders
tell application “Finder”
activate
set visible of every process whose visible is true and name is not "Finder" to false
-- then, quit all apps that use Cache so that the Cache Folders can be emptied
set allCacheAppNames to {"Eudora", "Explorer", "iPhoto", "Mozilla", "Netscape", "Safari"}
set allProcesses to application processes
repeat with i from 1 to (count of allProcesses)
set thisProcess to item i of allProcesses
set processName to name of thisProcess
repeat with eachCacheAppName in allCacheAppNames
if (processName contains eachCacheAppName) then
-- tell application processName to quit -- NO! for Panther???
run script "
try
tell application “” & processName & “” to quit
end try
"
exit repeat
end if
end repeat