AppleScript : get contextual menu of a window - macos

I need to script with applescript the equivalent of right-clicking inside a window of an app and selecting an option in the contextual menu.
Here's the code I'm using, inspired by some code I found in another thread :
tell application targetApp to activate
delay 0.2
tell application "System Events"
tell process targetApp
tell window 1 to perform action "AXShowMenu"
delay 0.2
keystroke "Open"
keystroke return
end tell
end tell
I don't get any compiler nor execution error, but nothing happens, as if no contextual menu option has been selected.
Any idea of what I missed ?
Thanks in advance.

Related

How to to select specific checkboxes in System Preferences?

I am trying to select the third checkbox of the Keyboard menu item and tab to change the basic fn key function with one run of the script. The rest of the code appears to work fine, but I just recently started trying to code at all so I have no idea.
Here is my current code:
tell application "System Preferences"
activate
set current pane to pane id "com.apple.preference.keyboard"
delay 1
tell application "System Events"
tell (click checkbox 3 of tab group 1)
delay 2
end tell
end tell
end tell
tell application "System Preferences" to quit
And here is the error message:
error "System Events got an error: Can’t get tab group 1." number -1728 from tab group 1
It looks like I'm just not defining it correctly, but I can't find out how to. Any help is appreciated!
Also, this is not needed but would it be possible to run the script without visibly opening the System Preferences application?
The following example AppleScript code was tested under macOS Catalina and clicks the Turn keyboard backlight off after checkbox at: System Preferences > Keyboard > Keyboard
As coded, it does the following:
Checks to see if System Preferences is running and if it is, it closes it so as to not have to see the UI flashing thru the different panes.
If System Preferences is not running it opens to the target anchor/pane without showing the UI.
Clicks the target checkbox.
Closes System Preferences
Example AppleScript code:
if running of application "System Preferences" then
try
tell application "System Preferences" to quit
on error
do shell script "killall 'System Preferences'"
end try
delay 0.1
end if
repeat while running of application "System Preferences" is true
delay 0.1
end repeat
tell application "System Preferences" to ¬
reveal anchor "keyboardTab" of pane id ¬
"com.apple.preference.keyboard"
tell application "System Events"
tell front window of application process "System Preferences"
repeat until (exists checkbox 3 of tab group 1)
delay 0.01
end repeat
click checkbox 3 of tab group 1
delay 0.1
end tell
end tell
tell application "System Preferences" to quit
Note: The example AppleScript code is just that and sans any included error handling, does not contain any additional error handling as may be appropriate. The onus is upon the user to add any error handling as may be appropriate, needed or wanted. Have a look at the try statement and error statement in the AppleScript Language Guide. See also, Working with Errors. Additionally, the use of the delay command may be necessary between events where appropriate, e.g. delay 0.5, with the value of the delay set appropriately.

Using AppleScript to modify settings/system preferences

I am trying to make an AppleScript that toggles automatic rearranging of spaces. I am able to get the AppleScript to open system preferences and go into mission control settings, however i am not sure how to check the box which i want to change.
tell application "System Preferences"
activate
end tell
tell application "System Events"
tell process "System Preferences"
click menu item "Mission Control" of menu "View" of menu bar 1
delay 2
tell window "Mission Control"
//additional code goes here
end tell
end tell
end tell
Is there a way to see what the components of the window are so i know if i need to go into a table, or something else, before i am able to access the check boxes that toggle the settings
This is an alternative method using a shell command via AppleScript, which has the benefit of not requiring System Preferences to be open/running/visible. It's also much faster.
If you do happen to have it open in order to monitor whether the script below works, bear in mind that the GUI (what you see) is not updated until you close System Preferences, and open it up again.
To set Automatically rearrange Spaces based on most recent use to true (i.e. so the checkbox is ticked):
do shell script "defaults write com.apple.dock 'mru-spaces' -bool true; killall Dock"
To set it to false, i.e. untick the checkbox, change true to false in the line of code above.
To toggle the setting, this short script will achieve that:
set currentSetting to ¬
(do shell script ¬
"defaults read com.apple.dock 'mru-spaces'") ¬
as integer as boolean
do shell script ¬
"defaults write com.apple.dock 'mru-spaces' -bool " & ¬
(not currentSetting) & ¬
"; killall Dock"
Note: Tested with MacOS High Sierra, but should work (I believe) in OS X Mavericks and later.
Other Settings
When switching to an application, switch to a Space with open windows for the application
do shell script "defaults write -g AppleSpacesSwitchOnActivate -bool true"
(or false if you want the option off.)
Group windows by application
do shell script "defaults write com.apple.dock 'expose-group-apps' -bool true; killall Dock"
(or false if you want the option off.)
Let me start by saying while both of the other answers prior to this one do work, nonetheless I wouldn't use either one of them for the following reasons.
The answer presented by shadowsheep works however it needlessly exposes the System Preferences GUI and I believe unless your system is really slow the value of the delay command is excessive by 50% and only one should be necessary in this use case.
The answer presented by CJK works however it uses killall Dock which is visually distracting and causes all minimized windows on all Desktops to be unminimized leading to further visual distractions, and clutters the Desktop(s), which can then require the User to cleanup the mess. Even without other windows open it's still more so a visual distraction then what I'll present.
Now every User has different work habits so maybe none of the reasons mentioned are of any consequence to you. Personally, I work between four virtual Desktops and can have dozens of windows opened in numerous apps across the Desktops with many, if not most minimized at times. Using killall Dock for me is the last thing I want to do most of the time.
With that said, here's an alternative to both of the existing answers prior to this one.
It's probably safe to say that most Users don't open and leave open System Preferences however the following example AppleScript code checks to see if it's running and if so closes it. This is so it can be opened without showing the GUI, so as not to have to see the the visual distraction of have the GUI change as the script progresses.
This example AppleScript code simply toggles the state of the target checkbox:
if running of application "System Preferences" then
quit application "System Preferences"
delay 1
end if
tell application "System Preferences"
reveal pane id "com.apple.preference.expose"
delay 1
tell application "System Events"
tell group 2 of window 1 of application process "System Preferences"
click checkbox "Automatically rearrange Spaces based on most recent use"
end tell
end tell
quit
end tell
This example AppleScript code conditionally clicks the target checkbox using 0 or 1 in if value is equal to 0 then click it. Use 0 to only click it if it's not checked and 1 to only click it if it's checked.
if running of application "System Preferences" then
quit application "System Preferences"
delay 1
end if
tell application "System Preferences"
reveal pane id "com.apple.preference.expose"
delay 1
tell application "System Events"
tell group 2 of window 1 of application process "System Preferences"
tell checkbox "Automatically rearrange Spaces based on most recent use"
if value is equal to 0 then click it
end tell
end tell
end tell
quit
end tell
Both example AppleScript code blocks shown work fast and without seeing the System Preferences GUI and the only visual effect is the Dock Tile for System Preferences does a single bounce and may not even be noticeable, especially when compared to the visual distraction of killall Dock.
Note that the value of the delay commands may need to be adjusted for your system, and or additional delay commands may or may not be needed. Adjust values of and or add/remove the delay commands as appropriate.
Note: The example AppleScript code is just that and does not employ any other error handling then what's shown and is meant only to show one of many ways accomplish a task. The onus is always upon the User to add/use appropriate error handling as needed/wanted.
This should to what you want.
In this example Automatically rearrange Spaces based on most recent use is the checkbox you want to check.
tell application "System Preferences"
activate
delay 2
set the current pane to pane id "com.apple.preference.expose"
delay 2
tell application "System Events"
click checkbox "Automatically rearrange Spaces based on most recent use" of group 2 of window "Mission Control" of application process "System Preferences"
end tell
quit
end tell
And this if you wanna check it only if it's not checked:
tell application "System Preferences"
activate
delay 2
set the current pane to pane id "com.apple.preference.expose"
delay 2
tell application "System Events"
tell checkbox "Automatically rearrange Spaces based on most recent use" of group 2 of window "Mission Control" of application process "System Preferences"
if (get its value) = 0 then click it
end tell
end tell
quit
end tell
And if you wanna list all the UIElements in the window:
set myArray to {}
tell application "System Preferences"
activate
delay 2
set the current pane to pane id "com.apple.preference.expose"
delay 2
tell application "System Events"
tell window "Mission Control" of application process "System Preferences"
repeat with uiElem in entire contents as list
set myArray to myArray & ((class of uiElem as string) & " : " & name of uiElem as string)
end repeat
end tell
end tell
end tell

How to close a floating window using AppleScript?

One of my application processes occasionally creates a floating window that I'd like to programmatically auto-close.
I have no problem checking for the existence of this window through its name, but then I am unable to close it with neither close window "windowname" nor tell window "windowname" to close.
E.g.:
tell application "System Events" to tell process "processname"
if exists window "windowname" then
close window "windowname"
end if
end tell
This result in:
error "System Events got an error: window "windowname" of process "processname" doesn’t understand the “close” message."
How can I close this window, then?
I can close a Finder window like this. Maybe you can do the same.
tell application "System Events"
tell process "Finder"
click button 1 of window 1
end tell
end tell
If "Command-W" closes the floating window, which it usually does, this will work:
tell application "System Events"
if exists window "<window name>" of process "<application name>" then
keystroke "w" using command down
end if
end tell
You can also use Automator instead of AppleScript proper to do this. Record yourself clicking the close button.
When I do this, Automator records the action as, I kid you not, Click the "<fill in title>" button.

Delay in an Alfred 2, using Automator and Apple Script to open "Stickies" and create a new note

Basically my goal is to code a key command (option-s) to activate Stickies and create a new note. Right now I have an Alfred 2 generated Automation which links the hot key to the following script:
on alfred_script(q)
tell application "Stickies" to activate
delay .2
tell application "Stickies" to activate
delay .01
tell application "System Events"
keystroke "n" using command down
end tell
end alfred_script
The two activate commands are my attempt to deal with a bug where it opens the application, but doesn't bring it to front. It works seamlessly when the application is open in the background, but it's slow and creates a screen flash when the application isn't already running. The delay is not coming from the application itself because I can open the application and hit command-n as fast as possible, and it always works.
(By the way if you have an idea for how I could hide all other notes and just show the new one, that would be awesome!)
Try this:
launch application "Stickies"
tell application "System Events" to tell process "Stickies"
click menu item "New Note" of menu "File" of menu bar 1
set frontmost to true
end tell
If you run the script by pressing option-s, there might not be enough time to release option before keystroke "n" using command down.
Or this doesn't raise the windows for other notes:
launch application "Stickies"
tell application "System Events" to tell process "Stickies"
click menu item "New Note" of menu "File" of menu bar 1
end tell
do shell script "open -a Stickies"
activate app "Appname" and set frontmost of "Appname" to true raise all windows, but do shell script "open -a Appname" raises only one window.
Hotkeys also have a short delay by default in Alfred, but you can reduce it by changing the trigger behavior:
You could try this alternate way, might have a different effect.
tell application "System Events"
tell process "Stickies"
set frontmost to true
keystroke "n" using command down
keystroke "Hello World" & linefeed & "I'm a new note!"
end tell
end tell
Hiding all other notes, i'd say start a new question for that.

Use AppleScript to change System Preferences without being visible?

I would like to change settings in System Preferences without the user seeing things happen.
If I have a script that starts like:
tell application "System Preferences"
activate
set current pane to pane "com.apple.preference.sound"
end tell
the System Preference window will be shown to the user.
I'd like to know if there is a way to do it in the background somehow, or at least keep the window minimized.
(Example script can be found in this question.)
You can just remove the activate command. System Events can perform actions in hidden windows.
tell application "System Preferences"
reveal anchor "keyboardTab" of pane "com.apple.preference.keyboard"
end tell
tell application "System Events" to tell process "System Preferences"
click checkbox 1 of tab group 1 of window 1
end tell
quit application "System Preferences"
If you open menus, they will be visible though.
tell application "System Preferences"
reveal anchor "TTS" of pane "com.apple.preference.speech"
end tell
tell application "System Events" to tell process "System Preferences"
tell pop up button 1 of tab group 1 of window 1
delay 0.1
click
if value is "Alex" then
click menu item "Kathy" of menu 1
else
click menu item "Alex" of menu 1
end if
end tell
end tell
quit application "System Preferences"
The brightness of displays can also be changed with brightness.c.
You might be able to do what you want with with the command line app defaults, there are some other command line apps that can manipulate other system stuff also like, pmset
Some things can be set using scripting additions also, for example the systems volumn can be set using the standard additions, you also you may be able to find other scripting additions to add more stuff.

Resources