I have a simple script that automates the command "Export Library" in Music. It does the following:
tell application "System Events"
tell process "Music"
set libmenu to menu item "Library" of menu "File" of menu bar 1
click menu item "Export Library…" of menu of libmenu
tell window 1
click button "Save"
tell sheet 1 to click button "Replace"
end tell
end tell
end tell
(So basically it opens the menu and clicks the obvious buttons, saving me a few clicks). However, after upgrading to Ventura (macOS 13.0), this stopped working. The command click button "Save" is failing with:
Can’t get button \"Save\" of window 1 of process \"Music\"."
I tried to say click button 1 or click button 2 instead, but that doesn't work. I then said name of every button and it printed
{missing value, missing value, missing value}
I couldn't find a good manual for AppleScript, but it does look like something changed in Ventura. Any hints will be appreciated!
Thanks,
OK, I replaced click button "Save" with:
repeat with b in (get buttons)
if name of b is "Save" then
click b
end if
end repeat
Interestingly, I can still click the "Replace" button directly without resorting to a loop.
Thanks!
OK! I found a hint for the answer here: Just add a short delay before trying to click on "Save"!
delay 0.5
click button "Save"
Without the delay, the the dialog doesn't seem to be ready and indeed if you do get buttons you will only see the 3 from the top left corner (close, minimize, zoom). With the delay, get buttons returns 6 buttons, including the "Save".
Related
enter image description here
I have the window of the picture above, save the configuration through stand-alone save, AppleScript can not click Save through click, the following script returns missing value, please ask in AppleScript, how to click static text
tell application "System Events"
tell process "WeChat"
click menu item "Proxy Settings..." of menu "WeChat" of menu bar 1
click radio button "Don't Use" of window "Proxy Settings"
delay 1
set focused to true
click static text "Save" of window "Proxy Settings"
end tell
end tell
```[enter image description here](https://i.stack.imgur.com/ZWJ9V.png)
tell application "System Events"
tell process "WeChat"
click menu item "Proxy Settings..." of menu "WeChat" of menu bar 1
click radio button "Don't Use" of window "Proxy Settings"
delay 1
set focused to true
click static text "Save" of window "Proxy Settings"
end tell
end tell
I don't have/use WeChat, so cannot examine the UI to confirm here, but static text elements—generally speaking—don't often have actions attached to them ("AXPress" is the name of the action that the click command aliases). From a design perspective, static text elements are intended as an inert label for some other UI element that plays a functional role. In this case, it looks like a button element, and its name is probably also "Save". button elements are also good candidates for attaching a whole bunch of actions to.
Therefore, instead of:
click static text "Save" of window "Proxy Settings"
you could try:
click button "Save" of window "Proxy Settings"
If that throws an error, it'll either be because the button element's name is not "Save", or the element is not a button. But you can find out what it is like this:
-- click button "Save" of window "Proxy Settings"
tell window "Proxy Settings" to get (the last UI element ¬
where the name of its actions contains "AXPress")
This will yield a reference to the object you're trying to click, by virtue of its actions necessarily containing one named "AXPress" (i.e. it responds to the click command), and its physical positioning almost certainly inferring it to be the last such UI element.
"Save" is not a button, and only one button can be found through the UI element, this button is a close button, and nothing else.
Can you rewrite this applescript for Monterey?
tell application "System Preferences" to reveal anchor "Seeing_ColorFilters" of pane "Accessibility"
tell application "System Events"
tell process "System Preferences"'s first window's first group's first tab group
click checkbox "Enable Color Filters"
tell first pop up button
click
-- if necessary, uncomment the following line to allow time for the menu to open
-- delay 0.1
tell its menu
click menu item 1
end tell
end tell
end tell
end tell
tell application "System Preferences" to quit
This code is a script that makes the display grayscale. I used to use this code in BigSur. However, after updating the version to Monterey, it stopped working. My Monterley version is 12.6.2.
Thanks,
The problem appears to be a timing issue. The menu that your script uses to select the greyscale option is no longer immediately available under Monterey 12.6.2. A short delay is required.
I took this script and enabled it one line at a time. With the System Preferences window already open and the color filters pane revealed, it worked all the way to the end.
So, I then ran the full script with System Preferences closed. It failed at the line:
click checkbox "Enable Color Filters"
with the error:
Script Error
System Events got an error: Can’t get group 1 of window 1 of process "System Preferences". Invalid index.
That error sounds like the window isn’t yet available. So I tried adding a delay in front of clicking the checkbox:
delay 0.1
click checkbox "Enable Color Filters"
The script then began to work as I assume you wished it to: the checkbox is checked, the first item on the menu (Greyscale) is selected, and the screen goes greyscale.
However, a hard-coded delay seems likely to fail if the system takes variable amounts of time to make the window available. So, rather than hardcode the delay, I added a loop to check for the existance of the desired checkbox:
repeat while not (exists checkbox "Enable Color Filters")
delay 0.1
end repeat
click checkbox "Enable Color Filters"
This version should work in past and future operating systems even if the timing changes, as long as the terminology remains the same.
The same technique should also work for your commented-out delay that waits for the menu to become available:
tell first pop up button
click
-- if necessary, allow time for the menu to open
repeat while not (exists its menu)
delay 0.1
end repeat
tell its menu
click menu item 1
end tell
end tell
Currently, the script toggles between greyscale and no filtering. That is, if the checkbox is already checked, this script will uncheck it. If your purpose is to ensure that the screen is always in greyscale, as your question implies, you may wish to verify the value of the checkbox first:
if the value of checkbox "Enable Color Filters" is 0 then
click checkbox "Enable Color Filters"
tell first pop up button
click
-- if necessary, allow time for the menu to open
repeat while not (exists its menu)
delay 0.1
end repeat
tell its menu
click menu item 1
end tell
end tell
end if
Checkboxes have a value of 0 or 1, depending on whether they’re currently checked (1) or unchecked (0).
If, on the other hand, your goal is for the script to toggle between the two states, there’s no reason to play around with the menu if you’re toggling color filters off:
if the value of checkbox "Enable Color Filters" is 0 then
click checkbox "Enable Color Filters"
tell first pop up button
click
-- if necessary, allow time for the menu to open
repeat while not (exists its menu)
delay 0.1
end repeat
tell its menu
click menu item 1
end tell
end tell
else
click checkbox "Enable Color Filters"
end if
Assuming the purpose is to guarantee the screen is in greyscale, the full script might end up looking like this:
tell application "System Preferences" to reveal anchor "Seeing_ColorFilters" of pane "Accessibility"
tell application "System Events"
tell process "System Preferences"'s first window's first group's first tab group
-- if necessary, allow time for the checkbox to become available
repeat while not (exists checkbox "Enable Color Filters")
delay 0.1
end repeat
--ensure that greyscale filters are enabled
if the value of checkbox "Enable Color Filters" is 0 then
click checkbox "Enable Color Filters"
tell first pop up button
click
-- if necessary, allow time for the menu to open
repeat while not (exists its menu)
delay 0.1
end repeat
tell its menu
click menu item 1
end tell
end tell
end if
end tell
end tell
tell application "System Preferences" to quit
I'm trying to select OK with the popup for scaling the screen with Apple script.
Does anyone know what I can add to this script to allow me to click OK?
Apple Script:
tell application "System Preferences"
reveal anchor "displaysDisplayTab" of pane "com.apple.preference.displays"
end tell
tell application "System Events" to tell process "System Preferences" to tell window "Built-in Retina Display"
click radio button "Scaled" of radio group 1 of tab group 1
click radio button 1 of radio group 1 of group 1 of tab group 1
(* Trying to click the ok button here *)
delay 1
click ((pop up buttons of sheet 1 of window 1) whose description is "OK")
end tell
quit application "System Preferences"
Or also rather does anyone know a trusted application that can graphically print out the labels of the UI when I visit them on my screen so I will know what to use when I say: "tell UIName"?
Thanks.
Solution 1: Press Return
Since you're using System Events anyway, and the button in question is selected by default (indicated by being highlighted in blue), just make sure that the preference pane is in focus and use System Events to hit the return key:
tell application "System Events" to keystroke return
It's quick, simple, and saves the hassle of identifying UI elements within the hierarchy. The drawback is that the preference pane has tone in focus, and if it loses focus before it receives the keystroke, the rest of the script will fail.
Solution 2: The One You Asked For
Regarding identification of UI elements within the GUI objects hierarchy, you got the class of the button in question wrong as well as its description.
The "OK" button is referenced like so:
tell application "System Events" to tell process "System Preferences" ¬
to get button "OK" of sheet 1 of window "Built-in Retina Display"
(window 1 is also fine). You can use the whose filter to target it instead, which would be done like this (via System Events and the System Preferences process):
get buttons of sheet 1 of window 1 whose name is "OK"
but all this does is ask AppleScript to search for a button whose name we know, then annoyingly give the result back to us as a list (the list structure can be flattened by requesting the first button of sheet 1...).
However, we do know its name and that there's only one of it, so we can reference it by name directly.
As a side-bar, if you quickly run this command:
get the properties of button "OK" of sheet 1 of window "Built-in Retina Display"
you'll be able to see that its description is merely "button", which isn't what you had hoped. Now run this command:
get the actions of button "OK" of sheet 1 of window "Built-in Retina Display"
which reveals it has one action available, AXPress (this is equivalent to a mouse click).
Therefore, finally, the way to click the button in a more satisfactory way than hitting the return key looks like this:
tell application "System Events" to tell process "System Preferences" ¬
to tell button "OK" of sheet 1 of window "Built-in Retina Display" ¬
to perform action "AXPress"
For exploring the GUI objects on the screen, I occasionally use the Accessibility Inspector that comes with Apple's XCode. It's vaguely useful, although inconveniently annoying with some of the discrepancies between the names by which it references objects and the names by which AppleScript does (they're also really subtle discrepancies, but enough to stop your script from working and send you into a frenzy for weeks).
So, actually, I just explore it programmatically myself in Script Editor.
What I did to solve your issue was to bring up the pane and the dialog box in question, then systematically tell the System Preferences process to get UI elements; then get buttons of UI elements; then get buttons of UI elements of UI elements, and stop when I saw a pair of buttons returned called "OK" and "Cancel". It can be pain-staking, but it'll get you the correct reference.
There are other ways too, but I would be moving beyond the scope of this question.
How to click "Go" button on go to finder dialog by applescript?
I have below code: "dialogObj" is the dialog of Go to Finder dialog, but the "click button 1 of searchFor" does not work in here.
-- Get the search for pop-up object
set searchFor to first sheet of dialogObj
-- Select all the text in the search field and press delete
key code 0 using command down
key code 51
delay 0.5
--Paste file name
keystroke "v" using {command down}
delay 0.5
-- Click the 'Go' button in the search for pop-up
set textField to value of first text field of first sheet of dialogObj
*click button 1 of searchFor*
delay 1
In macOS Sierra the text field has been replaced with a combo box:
Try
tell 1st sheet of dialogObj
set textField to value of combo box 1
click button "Go"
end
By the way: If you select the entire text you don't need to press Delete. Any pasted or typed text overwrites the selection.
You asked: "How to click "Go" button on go to finder dialog by applescript?"
Did you mean "Go to Folder" dialog, like this:
If so, then a simple RETURN will "click" the Go button:
tell application "System Events"
key code 36
end tell
I want to write a script which saves the images in few formats. the thing is the formats are shown based on some condition. I means some times there will be 5 formats and sometimes 8. I want to completely automate the working of these saving things. So i decided to write an applescript. Got UI browser and using that I can access each and every pop-up menus. I'm using loops to perform save operation. The thing is I am not getting where to end. So i came up with a thought that if i can get the number of items in the pop-up menu then it will be easy for me to carry out the task.
Can anyone help me out?
Well this is possible but you can't count the menu items directly. Communication is at the GUI-end and not directly to the application which means that the menu needs to appear before you can count it.
tell application "System Events"
tell process "Your application"
--we need to menu to appear first
click pop up button 1 of window 1
--now the menu appeared we can count the items in it
count menu items of menu 1 of pop up button 1 of window 1
--now hide the menu again by pressing escape
key code 53
end tell
end tell
Well counting is one way to check the menu but the other way is get all the values in it and then click the right menu item by it's name. This is, maybe not in your case, in general the best solution.
set menuItemToSelect to "Title of menu item I prefer to check"
tell application "System Events"
tell process "Your Application"
tell pop up button 1 of window 1
--Only continue if the menu item isn't already selected
if value of it is not equal to menuItemToSelect then
--we need to menu to appear first
click it
--now the menu appeared we can get the items
set menuItemTitles to name of menu items of menu 1
--check if the menu item exists
if menuItemToSelect is in menuItemTitles then
--menu item exists; click on it
click menu item menuItemToSelect of menu 1
else
--the menu item to select doesn't exist; hide the menu
key code 53
end if
end if
end tell
end tell
end tell