script no longer quitting all open apps under 10.15

-- get list of open apps
tell application "System Events" to set theapps to name of every application process whose visible is true and name is not "Finder"
set keepapp to {"AppleScript Editor"}
-- quit each app
repeat with closeapp in theapps
	if closeapp is not in keepapp then quit application closeapp
end repeat

used to work fine but does not touch certain applications running under 10.15.4.

any input as to why?

AppleScript Editor should probably be Script Editor, but otherwise the script works OK for me. What apps don’t quit and what error messages or prompts, if any, do you receive? Also, how are you running the script?

I don’t think it’s the issue, but you may want to try the following, which I’ve been using under Catalina without issue:

set doNotQuit to {"Finder", "Script Editor"}

tell application "System Events"
	set activeApps to name of every process whose background only is false
end tell

repeat with anApp in activeApps
	try
		if anApp is not in doNotQuit then tell application anApp to quit
	end try
end repeat

May you check the contents of the list theapps?

Maybe the name of some process doesn’t match the real name of the application.
Here having LibreOffice running I tested with:

-- get list of open apps
tell application "System Events" to set theapps to name of every application process whose visible is true and name is not "Finder"
--> {"fake_mojave", "TextEdit", "uBlock", "Script Editor", "Safari", "Mail", "Hex Fiend", "soffice"}
set keepapp to {"fake_mojave", "TextEdit", "uBlock", "Script Editor", "Safari", "Mail", "Hex Fiend"}
repeat with closeapp in theapps
	if closeapp is not in keepapp then quit application closeapp
	--> choose application as «class aprl» with prompt "Où se trouve soffice ?"
	--> error number -128
end repeat

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) vendredi 24 avril 2020 18:04:10

I wrote this enhanced version. It is much flexible and stable. It works with “strange” processes (as process “soffice” of LibreOffice.app) too. It will work as script or as application equally nice:


property keepApps : {name of current application, "Finder"}

tell application "System Events" to ¬
	set appNames to displayed name of (file of every application process whose visible is true)

repeat with appName in appNames
	if not (appName is in keepApps) then tell application appName to quit
end repeat

Are you sure ?
I ran it and I got :


-- don't click that, it's just a history lo !
tell application "System Events"
	get displayed name of file of every application process whose visible = true
		--> {"tout quitter.app", "Finder.app", "fake_mojave.app", "uBlock.app", "Xcode.app", "BBEdit.app", "Mail.app", "Safari.app", "LibreOffice.app", "Éditeur de script.app"}
end tell
tell application "tout quitter"
	quit

and entered an infinity loop ended by a force quit.
tout quitter.app is an applet.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 25 avril 2020 12:46:02

I am sorry - I forgot that from the last topic I still have the Finder setting “not to show name extensions”. The correct script is as follows:


property keepApps : {name of current application, "Finder"}

tell application "System Events" to ¬
	set appNames to name of (file of every application process whose visible is true)

repeat with appName in appNames
	set appName to text 1 thru -5 of appName
	if not (appName is in keepApps) then tell application appName to quit
end repeat

It changed nothing. With two added informative instructions it returned:

tell application "System Events"
	get name of file of every application process whose visible = true
		--> {"tout quitter.app", "Finder.app", "fake_mojave.app", "TextEdit.app", "uBlock.app", "Xcode.app", "BBEdit.app", "Mail.app", "Safari.app", "LibreOffice.app", "Script Editor.app"}
end tell
(*appName before : tout quitter.app*)
(*appName stripped : tout quitter*)
tell application "tout quitter"
	quit

and continue its infinite execution forcing me to force quit the Editor.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 25 avril 2020 15:07:18

If an app supports App Nap, a feature introduced in Mojave where an app can be put into a paused state, it will not be regarded as visible while napping.

There’s no guarantee that the app name and its file name are the same. Acrobat is a good example of this.

Here’s an ASObjC version:

use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

set theApps to current application's NSWorkspace's sharedWorkspace()'s runningApplications()
set thePred to current application's NSPredicate's predicateWithFormat:"activationPolicy == 0 AND NOT (localizedName IN %@)" argumentArray:{{"Finder", "Script Editor"}} -- edit to suit
set theApps to theApps's filteredArrayUsingPredicate:thePred
repeat with anApp in theApps
	anApp's terminate()
end repeat

It gets the list of apps much faster than System Events’s every process whose background only is false, but its main advantage is that app/process names aren’t required (except for the exceptions), so any differences are don’t matter.

You should keep 1 app at least - the current application.

I really liked the solution from Shane Stanley. It is truly more universal and faster than mine. I will just take it to my library without having to edit the name of the editor or applet itself:


use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use framework "AppKit"
use scripting additions
property keepApps : {name of current application, "Finder"}

set theApps to current application's NSWorkspace's sharedWorkspace()'s runningApplications()
set thePred to current application's NSPredicate's predicateWithFormat:"activationPolicy == 0 AND NOT (localizedName IN %@)" argumentArray:{keepApps}
set theApps to theApps's filteredArrayUsingPredicate:thePred
repeat with anApp in theApps
	anApp's terminate()
end repeat

Hello Shane.
Reading your post pushed me to give the content of my applet “tout quitter”.

use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
property forTesting : true
-- true --> execute a subset of the script plus informative instructions
-- false --> execute the normal tasks

property cleanApplicationState : false
-- true --> empty the folder "Saved Application State:"
-- false --> doesn't empty the folder -- my current setting

if forTesting then set {everyApps, filteredApps} to {{}, {}}

set runningApplications to current application's NSWorkspace's sharedWorkspace()'s runningApplications()
set keepApps to {"Finder", "tout quitter"}
set regularActivationPolicy to current application's NSApplicationActivationPolicyRegular
repeat with anApplication in runningApplications
	set appName to anApplication's localizedName() as text
	if forTesting then set end of everyApps to appName
	if anApplication's activationPolicy() is regularActivationPolicy and appName is not in keepApps then
		if forTesting then
			set end of filteredApps to appName
		else
			anApplication's terminate()
		end if
	end if
end repeat
if forTesting then return {everyApps, linefeed, linefeed, filteredApps}

# Now the applications are cleanly closed
if cleanApplicationState then
	# We may delete the Saved Application State datas
	try
		set p2AS to (path to library folder from user domain as text) & "Saved Application State:"
		tell application "System Events" to tell folder p2AS
			delete every folder -- some items are folders
			delete every file -- some items are aliases
		end tell # System Events …
	end try
end if

set p2pane to ((path to system preferences as text) & "StartupDisk.prefPane") as «class furl»
# Get four localized strings
set cancelBtn to localized string "CANCEL" in bundle p2pane
set restartBtn to localized string "RESTART" in bundle p2pane
set shutdownBtn to localized string "SHUTDOWN" in bundle p2pane
set prompt to localized string "RESTART?" in bundle p2pane

tell application "SystemUIServer" to display dialog prompt buttons {cancelBtn, restartBtn, shutdownBtn} default button 3 cancel button 1
set |éteindre| to (button returned of result) is shutdownBtn
# Now we may trigger shutdown or restart cleanly. Open documents were saved before.
tell application "System Events"
	if |éteindre| then
		shut down
	else
		restart
	end if
end tell # System Events

In real life the property forTesting is set to false.
When I set it to true it return :

{{“loginwindow”, “universalaccessd”, “tout quitter”, “talagent”, “SystemUIServer”, “Dock”, “Finder”, “Spotlight”, “com.apple.dock.extra”, “Centre de notifications”, “Box Finder Extension”, “imklaunchagent”, “com.apple.PressAndHold”, “CoreLocationAgent”, “Wi-Fi”, “Agent Photos”, “FolderActionsDispatcher”, “AirPlayUIAgent”, “popCalendar”, “Box”, “TISwitcher”, “SMARTReporter”, “FastScripts”, “fake_mojave”, “TextEdit”, “nbagent”, “HP Device Monitor”, “Box Helper”, “ViewBridgeAuxiliary”, “Legacy Color Picker Extensions (TextEdit)”, “uBlock”, “storeuid”, “Box UI”, “LaterAgent”, “Xcode”, “com.apple.CoreSimulator.CoreSimulatorService”, “BBEdit”, “Legacy Color Picker Extensions (BBEdit)”, “Aperçu”, “com.apple.speech.speechsynthesisd”, “Mail”, “Safari”, “Safari Networking”, “uBlock Safari Icon”, “Contenu web Safari (préchauffé)”, “LibreOffice”, “CoreServicesUIAgent”, “Éditeur de script”, “com.apple.security.pboxd”, “Événements système”}, "
", "
", {“fake_mojave”, “TextEdit”, “uBlock”, “Xcode”, “BBEdit”, “Mail”, “LibreOffice”, “Éditeur de script”}}

In real life, after several months of use I disabled the cleaning of Saved Application State.
Given that, when I reStart the machine, “tout quitter.app” is executed and installed in the Dock.
It’s why it’s listed in previous tests.
I assume that it’s because it has no provision to respond to a quit call that the previous tests brought an infinite running requiring to force quit the Script Editor.

I wish to add a comment about your script.
I feel that it requires some enhancement because, as is, it would fail to keep the Script Editor running.

use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

set theApps to current application's NSWorkspace's sharedWorkspace()'s runningApplications()
set thePred to current application's NSPredicate's predicateWithFormat:"activationPolicy == 0 AND NOT (localizedName IN %@)" argumentArray:{{"Finder", "Script Editor"}} -- edit to suit
set theApps to theApps's filteredArrayUsingPredicate:thePred

repeat with anApp in theApps
	--anApp's terminate()
	log (localizedName() of anApp) as string -- EDITED according to Shane Stanley's comment
end repeat

return:
(tout quitter)
(fake_mojave)
(TextEdit)
(uBlock)
(Xcode)
(BBEdit)
(Mail)
(Safari)
(LibreOffice)
(Éditeur de script)

I had to edit it as :

use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

property |NSURL| : a reference to current application's NSURL
property NSPredicate : a reference to current application's NSPredicate
property NSWorkspace : a reference to current application's NSWorkspace

set POSIXPath to POSIX path of (path to application "Script Editor")
(*
set theURL to current application's NSURL's fileURLWithPath:POSIXPath
--> error "Erreur dans Script Editor : NSURL ne comprend pas le message « fileURLWithPath_ »." number -1708 from NSURL
*)
set theURL to |NSURL|'s fileURLWithPath:POSIXPath
set {theResult, theValue, theError} to theURL's getResourceValue:(reference) forKey:"NSURLLocalizedNameKey" |error|:(reference)
set scriptEditor_loc to theValue as text
if scriptEditor_loc ends with ".app" then set scriptEditor_loc to text 1 thru -5 of scriptEditor_loc -- must drop the name extension
(*
set theApps to current application's NSWorkspace's sharedWorkspace()'s runningApplications()
--> error "Erreur dans Script Editor : NSWorkspace ne comprend pas le message « sharedWorkspace »." number -1708 from NSWorkspace
*)
set theApps to NSWorkspace's sharedWorkspace()'s runningApplications()
(*
set thePred to current application's NSPredicate's predicateWithFormat:"activationPolicy == 0 AND NOT (localizedName IN %@)" argumentArray:{{"Finder", scriptEditor_loc}} -- edit to suit
--> error "Erreur dans Script Editor : NSPredicate ne comprend pas le message « predicateWithFormat_argumentArray_ »." number -1708 from NSPredicate
*)
set thePred to NSPredicate's predicateWithFormat:"activationPolicy == 0 AND NOT (localizedName IN %@)" argumentArray:{{"Finder", "Script Debugger", scriptEditor_loc}} -- edit to suit
set theApps to theApps's filteredArrayUsingPredicate:thePred

repeat with anApp in theApps
	--anApp's terminate()
	log (localizedName() of anApp) as string -- EDITED according to Shane Stanley's comment
end repeat

I’m really puzzled by the need to define some properties.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 25 avril 2020 17:02:08

Added “Script Debugger” which is not localized in the list of ‘protected’ applications.

Are you sure of that ?

When I run this test version from Script Editor,


use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use framework "AppKit"
use scripting additions
property keepApps : {name of current application, "Finder"}

set theApps to current application's NSWorkspace's sharedWorkspace()'s runningApplications()
set thePred to current application's NSPredicate's predicateWithFormat:"activationPolicy == 0 AND NOT (localizedName IN %@)" argumentArray:{keepApps}
set theApps to theApps's filteredArrayUsingPredicate:thePred
repeat with anApp in theApps
	--anApp's terminate()
	log (localizedName() of anApp) as string -- EDITED according to Shane Stanley's comment
end repeat

I get :
(tout quitter)
(fake_mojave)
(TextEdit)
(uBlock)
(Xcode)
(BBEdit)
(Mail)
(Safari)
(LibreOffice)
(Éditeur de script)

Once more you forgot that name of current application is not localized.
Here it returns “Script Editor”
while Shane’s script lists localizedName of running applications.
As a result, Script Editor would be quitted.

I’m afraid that you will often miss this kind of behavior because you run your system in English.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 25 avril 2020 17:12:46

So, what to do? I would not like to correct the name of the editor or applet in the code each time. Give a solution for non-English systems, if possible.

Just take time to read what I posted to Shane in message #13 were I wrote about this feature before seeing your post.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 25 avril 2020 17:32:28

Well, Yvan, thanks for this. I tried your script in the post #13 and it worked for me fine. I just replaced the path to “Script Editor” with path to current application. May you test like me with path to current application and tell me if it works for your non English system?

I want to not hardcode the name of current application. Because I use multilpy choices for my scripts: Script Editor, Script Debugger, applet, droplet, mail rule, and so on… You understand me.

As I assume that your goal is to protect the editor with which you are running I make some enhancement.

use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

property NSPredicate : a reference to current application's NSPredicate
property NSWorkspace : a reference to current application's NSWorkspace

set protectedName to name of current application
if protectedName is not "Script Debugger" then
	set theBundle to path to application "Script Editor"
	set protectedName to localized string "CFBundleName" from table "InfoPlist" in bundle theBundle
	-- set protectedName to localized string "CFBundleDisplayName" from table "InfoPlist" in bundle theBundle -- same result
end if
(*
set theApps to current application's NSWorkspace's sharedWorkspace()'s runningApplications()
--> error "Erreur dans Script Editor : NSWorkspace ne comprend pas le message « sharedWorkspace »." number -1708 from NSWorkspace
*)
set theApps to NSWorkspace's sharedWorkspace()'s runningApplications()
(*
set thePred to current application's NSPredicate's predicateWithFormat:"activationPolicy == 0 AND NOT (localizedName IN %@)" argumentArray:{{"Finder", scriptEditor_loc}} -- edit to suit
--> error "Erreur dans Script Editor : NSPredicate ne comprend pas le message « predicateWithFormat_argumentArray_ »." number -1708 from NSPredicate
*)
set thePred to NSPredicate's predicateWithFormat:"activationPolicy == 0 AND NOT (localizedName IN %@)" argumentArray:{{"Finder", protectedName}} -- edit to suit
set theApps to theApps's filteredArrayUsingPredicate:thePred

repeat with anApp in theApps
	--anApp's terminate()
	log (localizedName() of anApp) as string -- EDITED according to Shane Stanley's comment
end repeat

It’s the running editor which will be protected.
At this time, the code in message #13 protect both of them.

As you may see, I use a cleaner code to grab the localized name of the Script Editor.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 25 avril 2020 18:11:52

I want to not hardcode the name of current application at all. Because I use multilpy choices for my scripts: Script Editor, Script Debugger, applet, droplet, folder action, mail rule, and so on… You understand me.

I tested this:


use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use framework "AppKit"
use scripting additions
property |NSURL| : a reference to current application's NSURL
property NSPredicate : a reference to current application's NSPredicate
property NSWorkspace : a reference to current application's NSWorkspace

set theURL to |NSURL|'s fileURLWithPath:(POSIX path of (path to current application))
set {theResult, theValue, theError} to theURL's getResourceValue:(reference) forKey:"NSURLLocalizedNameKey" |error|:(reference)
set currentApps_loc to theValue as text
if currentApps_loc ends with ".app" then set scriptEditor_loc to text 1 thru -5 of scriptEditor_loc

set theApps to NSWorkspace's sharedWorkspace()'s runningApplications()
set thePred to NSPredicate's predicateWithFormat:"activationPolicy == 0 AND NOT (localizedName IN %@)" argumentArray:{{currentApps_loc, "Finder"}}
set theApps to theApps's filteredArrayUsingPredicate:thePred

repeat with anApp in theApps
	anApp's terminate()
end repeat

Can you test is too, as is?

I tested with both editors and applet running :

use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

property |NSURL| : a reference to current application's NSURL

set POSIXPath to POSIX path of (path to current application)
(*
set theURL to current application's NSURL's fileURLWithPath:POSIXPath
--> error "Erreur dans Script Editor : NSURL ne comprend pas le message « fileURLWithPath_ »." number -1708 from NSURL
*)
set theURL to |NSURL|'s fileURLWithPath:POSIXPath
set {theResult, theValue, theError} to theURL's getResourceValue:(reference) forKey:"NSURLLocalizedNameKey" |error|:(reference)
set protectedName to theValue as text
-- stripping aways required here
if protectedName ends with ".app" then set protectedName to text 1 thru -5 of protectedName -- must drop the name extension

display dialog protectedName

It returned the correct values:
Script Debugger (which is never localized)
Éditeur de script on my machine running in French
fakeApplet when running an applet by a double click (this one was not localized)
I didn’t try with a mail rule but (1) I don’t see why it would fail (2) at least in French the name of Mail.app is not localized so I would see nothing if it didn’t work.

I guess that the best thing to do is to set, at least temporarily, your machine to run in Greek and make some tests on your side.

I was glad to have found a cleaner way to grab the localized name for Script Editor but, it doesn’t apply to your 3rd, 4th… cases
I hope that Shane will be able to give a cleaner code.
I searched in wCode help for infos about localizedName but found nothing allowing me to clean the code.
As you saw, I was a bit puzzled by the fact that the syntax used by Shane fails on my machine.
What a surprise, after a simple copy then paste in a blank window, the original instructions worked flawlessly so the current code is :

use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

set POSIXPath to POSIX path of (path to current application)

set theURL to current application's NSURL's fileURLWithPath:POSIXPath
set {theResult, theValue, theError} to theURL's getResourceValue:(reference) forKey:"NSURLLocalizedNameKey" |error|:(reference)
set protectedName to theValue as text
-- always required here
if protectedName ends with ".app" then set protectedName to text 1 thru -5 of protectedName -- must drop the name extension

set theApps to current application's NSWorkspace's sharedWorkspace()'s runningApplications()
set thePred to current application's NSPredicate's predicateWithFormat:"activationPolicy == 0 AND NOT (localizedName IN %@)" argumentArray:{{"Finder", protectedName}} -- edit to suit
set theApps to theApps's filteredArrayUsingPredicate:thePred

repeat with anApp in theApps
	--anApp's terminate()
	log (localizedName() of anApp) as string -- EDITED according to Shane Stanley's comment
end repeat

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 25 avril 2020 18:59:43