Help organize an applescript list alphabetically

Hi there BTT commune =)

In every mac out there Opt + command + esc will give us a force quit application window but only for running horses, for other processes we will have to resort to activity monitor, sloth, htop, etc. (for something with a GUI) or go into a terminal and pid exterminate.

I found the following applescript (copy pasted, zero-code-hability) to be almost a perfect way to kill single or multiple running processes quick; only annoyance: list is not in alphabetical order.

 

Is there a way to make the list appear alphabetically ordered?

 

tell application "System Events"
	set listOfProcesses to get name of every process
	tell me to set selectedProcesses to choose from list listOfProcesses with multiple selections allowed
end tell
--The variable `selectedProcesses` will contain the list of selected items.
repeat with processName in selectedProcesses
	do shell script "/usr/local/bin/quit " & quoted form of processName
end repeat

Thank you and long live BTT!! :crossed_swords::tada:

 


 
10-Jun-2018) Edited to use Jon Stowell's polite Quit

set my text item delimiters to linefeed
tell application "System Events" to set P to the name of every process as text

set my text item delimiters to space
set sh to the contents of {¬
	"printf", quoted form of P, ¬
	"|", "sort -u"} as text
do shell script sh

set ProcessList to paragraphs of the result

set PIDs to {}

repeat with P in (choose from list ProcessList ¬
	with title ("Running Processes") ¬
	with prompt ("Select processes to kill:") ¬
	OK button name ("Quit") ¬
	multiple selections allowed true ¬
	without empty selection allowed)
	
	tell application "System Events" to set the end of PIDs to ¬
		the unix id of the process named P
	
end repeat

if PIDs = {} then return

set my text item delimiters to space
set sh to {"kill -s ABRT", PIDs} as text
do shell script sh
2 Likes

NEVERMIND, found the muting switch =)

defaults write com.apple.CrashReporter DialogType none

 
 
That's awesome and super helpfu @CJK , thanks.

When I run the script I get the alphabetically ordered list (divided in two, maybe some are bkgd or system processes and the others active ones, dunno, it is perfectly fine) from which I can select one or several processes to be killed.
The only annoyance is that differently from the other script this one produces a "APP XX quit unexpectedly" dialog. Firstly, what can I change not to have to deal with these? If nothing can be done, are there some system settings to mute these warnings.

Merci bien

1 Like

Well done for finding the defaults setting.

I was going to suggest using kill by itself with no signal name, i.e. removing -s ABRT. Despite the name of the command, I believe kill by default gets apps to quit politely where possible, and therefore, often doesn’t produce an alert.

1 Like

Do the ones that come at the end all start with a capital letter ?

If you want to change this, replace sort -u with sort -du, which gives the letter "A" and the letter "a" equal priority.

1 Like

Yeah, that seems like a more sensible approach, as I'd like to keep being noticed when a process quits unexpectedly :+1: Super!

 

Do the ones that come at the end all start with a capital letter ?

Actually the ones at the beginning.

If you want to change this, replace sort -u with sort -du , which gives the letter "A" and the letter "a" equal priority.

sort -du doesn't seem to achieve intended result, list still divided

 
Abusing of your knowledge and patience, if in a similar script if I wanted to quit and then relaunch the app how would I proceed after do shell script sh ... I've found that a ps -p { then the PID} -o comm= will get the path of the given PID's process, but I have no idea how to implement that; monkey with an spectrometer trying to open a beer can :stuck_out_tongue:

Apologies. It's sort -uf

You wouldn't be able to do it using ps or its PID, because once the app has been terminated, it won't have a PID anymore and won't show up in ps.

Therefore, you need to know the name of the application (or its process name) in order to launch it again. For example, to launch iTunes from Terminal, you'd type:

open -a iTunes

which can be put into an AppleScript inside the do shell script command:

do shell script "open -a iTunes"

However, there's no need to use do shell script. AppleScript can do this natively:

activate application "iTunes"
1 Like

sort -uf does it perfectly, now the alphabetic order is 100% true =)

Regarding the relaunch, yeah that seems logical, not running = no PID :stuck_out_tongue:
I was trying to "reuse" the PID of the list's selection. But that is another adventure, right now I'm super happy with this result, BIG THANKS :pray:

Addendum
Finally I figured how to make BTT's script window focused; both in the relaunch and the kill processes above - so that I can immediately type text and locate the process. Before the applescript itself, I need to run yet another applescript, lets call it focus_on_BTT_AS.scpt

delay 0.3
tell application "System Events" to tell process "BetterTouchTool"
	perform action "AXRaise" of window 2
	set frontmost to true
end tell

wrapped in an osascript so that I can call it with a Execute Terminal Command Async action

osascript -e 'run script "path-to/focus_on_BTT_AS.scpt"'

Now I can go kill things and then bring them back to life :face_vomiting: :meat_on_bone:

I wouldn't reference the window by its index (2), as this is a changeable number that reflects the position in which the the window object sits relative to its siblings as determined by the order in which they each last received focus (window 2 simply being whatever window last had focus prior to the one that currently does).

Use the name of the window if you can (typically what's in the titlebar), or identify a property of the window that is unique to it and only it through which you can reliably reference it.

1 Like

Hey @CJK merci again for your guidance +)
Something like

set theTitle to "Running Processes"
tell application "System Events"
	tell process "BetterTouchTool"
		set frontmost to true
		perform action "AXRaise" of (window whose title is theTitle)
	end tell
end tell

?? :mushroom: :sunny:

No. It's actually exactly as you had it in your first script, except you should replace window 2 with window "Running Processes". The final code should look something like this:

tell application "System Events" to tell process "BetterTouchTool"
	perform action "AXRaise" of window "Running Processes"
	set frontmost to true
end tell
1 Like

@waxfingers, seeing your post tonight inspired me to revisit the script I first contributed at the top of this thread that retrieves the list of processes from which the user can select items for termination.

I rewrote the script tonight using AppleScriptObjC for a couple of reasons:

  1. It's faster
  2. It avoids having to invoke shell processes to sort the list and to kill the applications

The resulting script below is:

  1. A little bit shorter
  2. A little bit nicer to look at and read (notwithstanding the overly-red syntax highlighting issues that can't discern whether it's AppleScript or Objective-C, nor when a single quote is, in fact, an apostrophe)
  3. Overall, a cleaner, more efficient and robust implementation
use framework "Foundation"
use scripting additions

property this : a reference to the current application
property NSPredicate : a reference to NSPredicate of this
property NSSortDescriptor : a reference to NSSortDescriptor of this
property NSWorkspace : a reference to NSWorkspace of this

set Workspace to NSWorkspace's sharedWorkspace() 
# Keys: bundleIdentifier, processIdentifier, localizedName
set A to Workspace's runningApplications()'s sortedArrayUsingDescriptors:[¬
	NSSortDescriptor's sortDescriptorWithKey:"localizedName" ascending:yes ¬
	selector:"caseInsensitiveCompare:"]

set P to choose from list A's localizedName as list ¬
	with title ("Running Processes") ¬
	with prompt ("Select processes to kill:") ¬
	OK button name ("Quit") ¬
	multiple selections allowed true ¬
	without empty selection allowed

repeat with proc in (A's filteredArrayUsingPredicate:(NSPredicate's ¬
	predicateWithFormat:"localizedName IN %@" argumentArray:{P}))
	
	proc's terminate()
	# OR: proc's forceTerminate()
	
end repeat

I'm not sure what additions/changes you needed to make to the original script in order to integrate your additional functionality, and you may not wish to have to fiddle around with figuring out how to make similar changes to this new script, especially when what you now have is working the way you want. But I thought it was still worthwhile posting this revision for any other readers who might be interested.

Despite what it looks like, the code is still AppleScript, and you can add the snippets of code we've been discussing tonight to it just as you would any other AppleScript.

1 Like

Wow that's a totally new rewriting!!! And to think of its humble start, now is royalty 8D je je je.
There was no fiddling around; I've already incorporated your new code and works flawlessly; it does feel a bit faster. Once again a BIG THANK YOU @CJK, dunno about other users, but this is super useful to me :+1: :beers:

1 Like