How would I quit all running user applications using Applescript?
It's okay... I think I found my answer:
tell application "System Events" to set the visible of every process to true
set white_list to {"Finder"}
try
tell application "Finder"
set process_list to the name of every process whose visible is true
end tell
repeat with i from 1 to (number of items in process_list)
set this_process to item i of the process_list
if this_process is not in white_list then
tell application this_process
quit
end tell
end if
end repeat
on error
tell the current application to display dialog "An error has occurred!" & return & "This script will now quit" buttons {"Quit"} default button 1 with icon 0
end try
After some googling, I found a better approach:
It uses background only to build the initial app list, rather than
visible is true. The difference is that the other scripts will fail
to quit an app that's been hidden with ⌘H.
It provides an exclusions
list so that, for example, you can prevent your script editor from
quitting each time you test the script.
Adapted from a thread on MacScripter.
-- get list of open apps
tell application "System Events"
set allApps to displayed name of (every process whose background only is false) as list
end tell
-- leave some apps open
set exclusions to {"AppleScript Editor", "Automator", "Finder", "LaunchBar"}
-- quit each app
repeat with thisApp in allApps
set thisApp to thisApp as text
if thisApp is not in exclusions then
tell application thisApp to quit
end if
end repeat
tell application "System Events" to set the visible of every process to true
set white_list to {"Finder"}
try
tell application "Finder"
set process_list to the name of every process whose visible is true
end tell
repeat with i from 1 to (number of items in process_list)
set this_process to item i of the process_list
if this_process is not in white_list then
tell application this_process
quit
end tell
end if
end repeat
on error
tell the current application to display dialog "An error has occurred!" & return & "This script will now quit" buttons {"Quit"} default button 1 with icon 0
end try
tell application "System Events" to set quitapps to name of every application process whose visible is true and name is not "Finder"
repeat with closeall in quitapps
quit application closeall
end repeat
Related
I made the following code to open a website, insert some required text, click "View", and download the resulting document. It runs perfectly if I manually click on it. It also works if I schedule a calendar event to call it when I am sitting in front of my Mac. I have tried every combination of keeping the display on/off and screen unlocked/locked. For some reason, it doesn't seem to work at 5:30am and 2:00pm when I set it to run. I have checked to make sure the disk and Mac are not going to sleep as well. Any thoughts on what I am doing wrong would be greatly appreciated.
--Quit Safari before the program starts
tell application "Safari"
close every window
end tell
--empty "Downloads" folder
tell application "System Events"
delete (every file of folder ("/Users/97pubs/Downloads"))
end tell
--opens DINS website
tell application "Safari"
make new document with properties {URL:"https://www.notams.faa.gov/dinsQueryWeb/"}
activate
ignoring white space
tell front document to repeat until its text contains "About DINS"
end repeat
end ignoring
log "Finished loading"
end tell
delay 2
--Function to press DoD banner on DINS website
to clickClassName(theClassName, elementnum)
tell application "Safari"
do JavaScript "document.getElementsByClassName('" & theClassName & "')[" & elementnum & "].click();" in document 1
end tell
end clickClassName
clickClassName("ui-state-default", 0)
delay 2
--Function to input ICAO abbreviations on the page
to inputByName(theName, num, theValue)
tell application "Safari"
do JavaScript "
document.getElementsByName('" & theName & "')[" & num & "].value ='" & theValue & "';" in document 1
end tell
end inputByName
inputByName("retrieveLocId", 0, "kmaf")
delay 2
--Function to click "View NOTAMs" on page
to clickName(theName, elementnum)
tell application "Safari"
do JavaScript "document.getElementsByName('" & theName & "')[" & elementnum & "].click();" in document 1
end tell
end clickName
--Clicks "View NOTAMs" on page
clickName("submit", 0)
--Waits for next window to completely load before continuing
tell current application
tell application "Safari"
tell window 1
repeat until (exists tab 2)
delay 1
end repeat
ignoring white space
tell front tab to repeat until its text contains "DINS Disclaimer"
end repeat
end ignoring
end tell
end tell
end tell
delay 1
--Clicks "Save all NOTAMs" on page
clickName("button", 1)
delay 2
--Waits for download to complete before continuing
set someFolder to "/Users/path/to/save/location/" -- put your download folder path here
if not (waitForFilesToCopy into someFolder for (10 * minutes)) then
display alert "Error with downloads" message "The downloads did not complete in the time allowed."
if button returned of the result is "Cancel" then error -128
end if
to waitForFilesToCopy into theFolder for timeToWait
(*
waits up to the timeToWait for files to be copied/downloaded to theFolder the test is based on the size of the folder not changing after several seconds the rough timeToWait may need to be adjusted if copying several files/folders parameters - theFolder [mixed]: the folder to check timeToWait [integer]: a maximum timeout value in seconds returns [boolean]: true if copy/download finished, false if timeout
*)
set {theFolder, possible, interval} to {theFolder as text, false, 2} -- change the check interval as desired
tell application "System Events" to set currentSize to size of disk item theFolder -- get initial size
repeat (timeToWait div interval) times -- check every interval seconds
delay interval
tell application "System Events" to set newSize to size of disk item theFolder -- recheck size
if (newSize is equal to currentSize) then
if possible then -- no change since last time
return true -- success
else -- one more time...
set possible to true
end if
else -- update size & possible switch
set {currentSize, possible} to {newSize, false}
end if
end repeat
return false -- fail (timeout)
end waitForFilesToCopy
--Rename PDF to "5 Local NOTAMs.pdf"
tell application "System Events" to set name of file "/Users/path/to/save/location/temp.pdf" to "5 Local NOTAMs.pdf"
--Move NOTAMs to "CrewPapers" folder
tell application "Finder"
move POSIX file "/Users/path/to/save/location/5 Local NOTAMs.pdf" to POSIX file "/Users/path/to/new/location" with replacing
end tell
--Close Safari and Preview windows
tell application "Safari"
close every window
end tell
tell application "Preview"
close every window
end tell
This script works when terminal application(or any application) is not in FullScreen mode. It will return the correct value of false. When you make the application fullscreen it returns any empty value. The only thing I can think of is that when you go fullscreen it puts it on a different desktop? Am I missing something to activate the app differently now that it is fullscreen?
tell application "System Events" to set the visible of every process to true
set white_list to {"Finder", "AppleScript Editor", "Google Chrome"}
tell application "System Events"
set process_list to the displayed name of every process whose visible is true
set process_number to (number of items in process_list)
set myList to process_list
end tell
repeat with theItem in myList
if theItem is not in white_list then
log theItem
tell application "System Events" to tell process theItem
set isFullScreen to the value of attribute "AXFullScreen" of windows
end tell
end if
end repeat
return theItem & " application is FullScreen: " & isFullScreen
This line won't work as written...
set isFullScreen to the value of attribute "AXFullScreen" of windows
"windows" will return a list of windows and you can't get that attribute from a list. So you would want to write it as...
set isFullScreen to the value of attribute "AXFullScreen" of window 1
However, with that said I tried this and it seems you can't get the windows from a full screen process. The list of windows is always empty {}. So this approach of determining if an application is full screen will not work.
You'll need to think of another way to figure out if an application is full screen. I tried a couple things and couldn't find a solution. Sorry.
Applescript newbie question again :) I am trying to create a small applescript that will allow me to select multiple items from a list of currently running applications and then quit those selected apps. Something like this works but rather than having to click on each dialog it would be much easier to chose from a list.
tell application "System Events"
repeat with p in every process
if background only of p is false then
display dialog "Would you like to quit " & name of p & "?" as string
end if
end repeat
end tell
Any and all help would be greatly appreciated!
Thanks!
Try this:
tell application "System Events"
set listOfProcesses to (name of every process where background only is false)
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 "Killall " & quoted form of processName
end repeat
tell application "System Events"
set processList to get the name of every process whose background only is false
set processNameList to choose from list processList with prompt "Select process to quit" with multiple selections allowed
if the result is not false then
repeat with processName in processNameList
do shell script "Killall " & quoted form of processName
end repeat
end if
end tell
you can use this script which is much simpler
tell application "Finder"
get the name of every process whose visible is true
end tell
You can try this
tell application "System Events"
set AppName to name of every process whose background only is false
choose from list AppName OK button name "Ok" cancel button name "Cancel"
end
& (name of every process whose (name is "AppName") can be added to Michele Percich's and Parag Bafna's solutions to include specific menu bar applications by name.
tell application processName to quit can be used instead of do shell script "Killall " & quoted form of processName.
tell application "System Events"
set processList to ¬
(name of every process where background only is false) & ¬
(name of every process whose ¬
(name is "AppName") or ¬
(name is "AnotherAppName"))
tell me to set selectedProcesses to choose from list processList with prompt "Select process(es) to quit:" with multiple selections allowed
end tell
if the result is not false then
repeat with processName in selectedProcesses
tell application processName to quit
end repeat
end if
I wrote this following AppleScript code a few years back. I consider it to be a “Must Have” because I use it almost every single day.
This code will generate a list of Visible and Hidden application processes, allowing multiple items to be selected to kill their processes. The first items in the list will be visible application processes (not sorted alphabetically), then an empty list item (used to separate the visible from the hidden processes), and the remaining list items will be the hidden application processes (sorted alphabetically)
use framework "Foundation"
use scripting additions
property appsToKill : missing value
property NSArray : a reference to current application's NSArray
listAllAppProcesses()
activate
set killApp to (choose from list ¬
appsToKill with title "Choose The App To Kill" with prompt ¬
"Choose The App/Apps To Kill" & linefeed & linefeed ¬
& "The Empty List Item Separates The Visible From The Hidden Applications" OK button name ¬
"OK" cancel button name "CANCEL" with multiple selections allowed)
set pidList to {}
if killApp is not false then
tell application "System Events"
repeat with i from 1 to count of killApp
set thisItem to item i of killApp
tell application process thisItem
set thePID to unix id
set end of pidList to thePID
end tell
end repeat
end tell
else
return
end if
set text item delimiters to space
do shell script ({"kill -9", pidList} as text)
on listAllAppProcesses()
tell application "System Events"
set visibleAppsToKill to name of every application process ¬
where visible is true
set invisibleAppsToKill to name of every application process ¬
where visible is false
set aList to ((NSArray's arrayWithArray:invisibleAppsToKill)'s ¬
sortedArrayUsingSelector:"caseInsensitiveCompare:") as list
set appsToKill to visibleAppsToKill & "" & aList
end tell
end listAllAppProcesses
If you want it from Terminal, you can use a simple script like this quit.rb
The following example AppleScript code is pretty straight forward and will gracefully quit the selected application(s), providing the selected application(s) is (are) in a stable state:
tell application "System Events" to ¬
set appList to the name of ¬
every process whose visible is true
set quitAppList to ¬
choose from list appList ¬
with multiple selections allowed
repeat with thisApp in quitAppList
quit application thisApp
end repeat
When I present a list to choose from, I prefer to have it in alphabetical order and to that end I use a handler to first sort the list before presenting it:
on SortList(thisList)
set indexList to {}
set sortedList to {}
set theCount to (count thisList)
repeat theCount times
set lowItem to ""
repeat with i from 1 to theCount
if i is not in the indexList then
set thisItem to item i of thisList as text
if lowItem is "" then
set lowItem to thisItem
set lowItemIndex to i
else if thisItem comes before lowItem then
set lowItem to thisItem
set lowItemIndex to i
end if
end if
end repeat
set end of sortedList to lowItem
set end of indexList to lowItemIndex
end repeat
return the sortedList
end SortList
To use this with the first block of code presented I typically add handlers at the bottom of my code and then to use it, add the following example AppleScript code between the tell application "Finder" to ¬ and set quitAppList to ¬ statements:
set appList to SortList(appList)
Note: I acquired this particular handler somewhere on the Internet too many years ago to remember and unfortunately lost who to credit it to. My apologies to whomever you are.
I am attempting to write an applescript script that will allow me to resize all windows of all running applications whenever I choose (I currently use Stay, but find that it is glitchy at times, so I want to "re-invent" it)
I have been following some applescripting tutorials and have come up with the following code to do so, but it is buggy:
tell application "Finder"
set rect to bounds of window of desktop
end tell
property excludedApplicationNames : {"Finder"}
tell application "System Events"
say "a"
repeat with theProcess in processes
say "b"
if background only of theProcess is false then
say "c"
set theProcessName to name of theProcess as string
if theProcessName is not in excludedApplicationNames then
say theProcessName
tell application theProcess
set bounds of windows of process theProcess to rect
end tell
end if
end if
end repeat
end tell
say "done"
The problem is that when this code encounters my only terminal window (with several open tabs), it error: System Events got an error: Can’t set application (item 2 of every process) to {0, 0, 1280, 900}.System Events got an error: Can’t set application (item 2 of every process) to {0, 0, 1280, 900}.
Changing tell application theProcess to tell application theProcessName doesn't help (same error), and neither does changing it to tell application "System Events" (Error: System Events got an error: Can’t make item 2 of every process into type integer.)
Interestingly, this works as expected:
tell application "Finder"
set rect to bounds of window of desktop
end tell
tell application "Terminal"
repeat with theWindow in windows
set bounds of theWindow to rect
end repeat
end tell
So I'm very confused.
What am I doing wrong? How can I fix this?
tell application "Finder"
set {0, 0, dtw, dth} to bounds of window of desktop
end tell
tell application "System Events"
repeat with p in (processes where background only is false)
tell p
if name is not in {"Finder"} then
set position of windows to {0, 0}
set size of windows to {dtw, dth}
end if
end tell
end repeat
end tell
Took about 3 seconds on my Mac
Maximizes Terminal windows to fill the screen (except for the 4px area taken up by Dock)
tell application "Finder"
set dtb to bounds of window of desktop
end tell
tell application "System Events"
bundle identifier of processes where background only is false
end tell
repeat with bid in result
tell application id bid
try
if name is not in {"Finder"} then
set (bounds of windows where visible is true) to dtb
end if
end try
end tell
end repeat
Took about 0.3 seconds on my Mac
Doesn't work with all applications like Preview or Reeder
Uses bundle identifiers because a few applications have different process and application names
Resizes Terminal windows so that they have a few pixels empty space above and below them
I use this script to maximize windows:
try
tell application "Finder" to set dtb to bounds of window of desktop
tell application (path to frontmost application as text)
if name is in {"Terminal"} then
error
else
set bounds of window 1 to dtb
end if
end tell
on error
tell application "System Events" to tell (process 1 where it is frontmost)
try
click (button 1 of window 1 where subrole is "AXZoomButton")
end try
end tell
end try
In many applications that don't have basic AppleScript support the zoom button also maximizes windows to fill the screen.
This one take the size of the dock into account. I have mine on the right side of the monitor, but it should be easy to modify to accommodate the dock being on the bottom.
tell application "Finder"
set dtb to bounds of window of desktop
end tell
tell application "System Events" to tell process "Dock"
set dockDimentions to size in list 1
set dockWidth to item 1 of dockDimentions
end tell
tell application "System Events"
bundle identifier of processes where background only is false
end tell
repeat with bid in result
tell application id bid
try
if name is not in {"Finder", "System Preferences", "Notepad", "Terminal", "Activity Monitor"} then
set x to item 1 of dtb
set y to item 2 of dtb
set w to (item 3 of dtb) - dockWidth
set h to item 4 of dtb
set (bounds of windows) to {x, y, w, h}
end if
end try
end tell
end repeat
This eventually did the trick for me:
property blacklist : {"Finder", "Preview", "Console", "AppleScript Editor", "Spotify", "TaskCoach"}
property buttonApps : {"LyX", "Eclipse"}
property buttonMaps : {{name:"LyX", Button:1, pname:"lyx"}, {name:"Eclipse", Button:2, pname:"eclipse"}}
tell application "Finder" to set theBounds to bounds of window of desktop
tell application "System Events"
set bids to bundle identifier of processes where background only is false
end tell
repeat with bid in bids
tell application id bid
if name is not in blacklist then
set appName to name as string
if name is "Terminal" then
set newBounds to {0, 0, (item 3 of theBounds) - 10, item 4 of theBounds}
repeat with theWindow in windows
if visible of theWindow is true then
say appName
set bounds of theWindow to newBounds
end if
end repeat
else if name is not in buttonApps then
repeat with theWindow in windows
if visible of theWindow is true then
set bounds of theWindow to theBounds
end if
end repeat
else if name is in buttonApps then
-- get the buttonNumber
repeat with buttonApp in buttonMaps
if (name of buttonApp as string) is appName then
set theButton to Button of buttonApp
end if
end repeat
tell application "System Events"
repeat with theProcess in (processes where bundle identifier is bid)
try
tell theProcess to tell window 1 to click button theButton
end try
end repeat
end tell
end if
end if
end tell
end repeat
Note that "Spotify" and "Task Coach" are blacklisted because I am not able to resize them by:
setting the window bounds
clicking on the green button
clicking on "Window">"Zoom" in the menu bar
using the ⌘F10 shortcut that I had mapped it to.
If anyone is able to come up with a better solution, I'm all ears
I am trying to write an applescript script that resizes all open windows. In order to make sure that I'm getting to all the windows, I'm making my script say the name of the application as well as the number of open windows of that application.
Interestingly, while I hear the names of all my open applications, my script says that they all have 0 windows open. How can I fix this issue?
Here's my code:
tell application "System Events"
repeat with theProcess in (every process)
if background only of theProcess is false then
if name of theProcess is not "Finder" then
if name of theProcess is "Google Chrome" then
say "Chrome woo hoo"
say (count windows as string)
else
say name of theProcess as string
say (count windows as string)
tell theProcess
repeat with theWindow in windows
say "found a window of"
say (name of theProcess) as string
tell theWindow
click button 2
end tell
end repeat
end tell
end if
end if
end if
end repeat
end tell
I'm on Mac OS X 10.7.5, using automator 2.2.4 to write/run this applescript
You have to tell the process to count windows. After all it's the process that knows about its windows, not system events.
You have told the process to say its name e.g. "say name of theProcess as string" however you only use "say (count windows as string)"... no process is tied to that. Try "count windows of theProcess". Basically you have lines where sometimes you tell the process, other times you don't, and other times where you tell the process even though you've already told the process, so you do it twice. That's where you have "say (name of theProcess) as string" but that code is inside a "tell theProcess" block so it's already being told to theProcess.
Really you need to go through your code and be more precise. A tip... if you want to click a button in a window then the window must be frontmost on the screen otherwise you can't click it. Another tip... "name" is already a string so you don't need to coerce that to a string.
By the way, I agree with Michael Dautermann's comment to your post... there will be processes where you won't get access. But you'll find that out as you progress.
Here's how I would write your code. Basically I would get all of the variables at the beginning using a "tell theProcess" block. Then I can do stuff with those variables. I hope that helps. Notice that I only made the process frontmost which means if it has multiple windows open it will only click a button on the front window. You'll have to add code to make each window come to the front before you can click its button. Good luck.
tell application "System Events"
repeat with theProcess in processes
if not background only of theProcess then
tell theProcess
set processName to name
set theWindows to windows
end tell
set windowsCount to count of theWindows
if processName is "Google Chrome" then
say "Chrome woo hoo"
say windowsCount as text
else if processName is not "Finder" then
say processName
say windowsCount as text
if windowsCount is greater than 0 then
repeat with theWindow in theWindows
say "found a window of " & processName
tell theProcess
set frontmost to true
tell theWindow
click button 2
end tell
end tell
end repeat
end if
end if
end if
end repeat
end tell
I create a list of all open windows of visible applications on Mavericks like this:
tell application "System Events"
set this_info to {}
repeat with theProcess in (application processes where visible is true)
set this_info to this_info & (value of (first attribute whose name is "AXWindows") of theProcess)
end repeat
this_info -- display list in results window of AppleScript Editor
end tell
You need to allow any app using this to access the interface under Accessibility.