Ventura System Preferences Scripts

Hello.

With the new structuring of the Ventura version, the scripts that were valid for configuring System Preferences modules (now with a different name) currently no longer work and the very useful help found in MacScripter on this matter, are now obsolete.

I have great confusion to use in the scripts the terms used for the manipulatable elements in System Preferences (window, pane, anchor, table, row, scroll area, splitter group, tab group, static text, UI element, checkbox, button, radio button, etc.) and even in the concept of some of them.

I would appreciate references, both in MacScripter and in other sources, to teach me the necessary knowledge to solve the doubts I have about the mentioned elements and, above all, the use of them to be able to correct and redo the old System Preferences scripts that have stopped working, which are almost all of them.

Thanks in advance for any kind of help.

There are two resources I use for figuring out the UI scripts, other than searching forums.

One is UI Browser, which unfortunately isn’t for sale anymore, but you can still download the last version and use a free trial: https://latenightsw.com/freeware/ui-browser/

The other is Script Debugger. https://latenightsw.com/ In Script Debugger, just open the System Preferences pane you want to automate, and run a simple script like this:

tell application "System Events"
	tell application process "System Preferences"
		set aWindow to window 1
	end tell
end tell

Then you can open the “aWindow” variable in the inspector and drill down through what UI elements are there and find the ones you’re looking for. When you find something you want to address, you can drag and drop it out into the script window and Script Debugger will generate the “tell” hierarchy for that element for you.

Sometimes it’s hard to get the syntax exactly right, UI scripting can be finicky. But between UI Browser and Script Debugger for exploring the UI, referencing code examples I find online for manipulating similar elements, and as a last resort, posting specific questions here to the forums, I can usually figure it out.

Hello, t.spoon. :wink:

Thank you very much for your kindness in providing the resources you know of so that I can try to understand the apparent tongue twister involved in focusing and configuring the elements that make up the many and varied System Settings panels.

I am amazed at how little (or rather, no) information Apple provides to users.

Moving forward on this issue looks like it is going to be a slow road, fraught with difficulties and multiple headaches.

Receive my thanks for your help in sharing your time and knowledge with me.

Regards.

In addition to what t.spoon said I would add that some settings that can be changed in System Preferences can be changed with other methods (shell scripting, etc.)

If you specify which specific settings you’re working with, we may be able to provide alternatives.

Hello, stockly. :slight_smile:

Thank you very much for taking an interest in my demand for help.

I am not interested in a particular setting but in understanding and learning the logic used to write the endless statements used in the scripts to focus and finally configure the elements of the various System Settings panels, such as,

click UI element 4 of group 1 of scroll area 1 of group 1 of group 2 of splitter group 1 of group 1 of window “accessibility”. :rolleyes: :frowning:

I am an eternal appleScript amateur learner (and not with very good results despite the amount of time I put into it). I completely ignore other methods such as shell scripting, AppleScriptObjC, etc.

That’s why I’m looking for AppleScript sources where I can get to learn what I’m interested in.

Thank you very much, again, for your willingness.

Regards.

In AppleScript GUI scripting you could use class of UI elements it will return every class of UI element in target tell block.

In other words.

tell application "System Events" to tell application process "System Preferences"
        set frontmost to true
	class of UI elements
end tell

Will return {window, menu bar}

Next you could do

tell application "System Events" to tell application process "System Preferences"
	set frontmost to true
	tell window 1
		class of UI elements
	end tell
end tell

So what you are doing is… return class of UI elements to you find the target UI elements.
You could ask ex. tell buttons to its name but not all UI elements have names and instead
use missing value. You could then use index number ex. tell button 3 to click

Doing this could take time, and some UI elements needs to be clicked to reveal its UI element.
To understand it all takes practice and could become very complex. I still use Monterey on my machine so I do not have the issue

This example will click the red dot upper left corner of System Preferences window

tell application "System Events" to tell application process "System Preferences"
	set frontmost to true
	tell window 1
		tell button 3 to click
	end tell
end tell

If the name of button is missing value, we could make name and set a integer to it.
To make the code easier to read and understand.

tell application "System Events" to tell application process "System Preferences"
	set frontmost to true
	tell window 1
		set quitWindow to 3
		tell button quitWindow to click
	end tell
end tell

Here is example of using ASObjC to build a dictionary of every checkbox in General pane.
This script have been running on Monterey 12.6.2 The checkbox return integer value of boolean. So I have converted it to boolean value and set missing value to a string. In this case the missing value was “Auto”

use framework "Foundation"
use scripting additions

tell application "System Preferences"
	reveal pane "General"
	delay 0.2
end tell

set theDict to current application's NSMutableDictionary's dictionary()

tell application "System Events" to tell application process "System Preferences"
	set frontmost to true
	tell window 1
		tell every checkbox to set {theNames, theValues} to {its name, its value}
		repeat with i from 1 to count theValues
			if (item i of theNames) contains missing value then
				set item i of theNames to "Auto"
			end if
			(theDict's setObject:((item i of theValues) as boolean) forKey:(item i of theNames))
		end repeat
		-- quit the window
		tell button 2 to click
	end tell
end tell

return theDict as record

Hello Fredrik71. :smiley:

Thank you very much from the bottom of my heart for all the time you have spent, with your very didactic examples, to put a little light in the middle of a darkness as big as my ignorance in this field.

Unfortunately, an error occurs when trying to compile the examples, probably due to the different structure of the graphical environment of the new “System Settings” compared to the old “System Preferences”.

tell application "System Events" to tell application process "System Settings"
	set frontmost to true  --Error
-- System Events has detected an error: Application process "System Settings" cannot be set to true.
	tell window 1  -- Error 
-- System Events has detected an error: Unable to get window 1 of application process "System Settings". Invalid index.
		class of UI elements
	end tell
end tell

It is a support point to start from and I hope it is the beginning to achieve a sufficient degree of satisfaction.

Best regards.

I have Ventura as VM and I couldn’t get it to work I mean do follow the dictionary.
I got the GUI Script to work but its far more complicated or maybe I have spend less time to
understand it. I’m not a user of Ventura I still use Monterey.

Your code looks correct, but you could do GUI Scripting on other application. The process is the same you only change the application process to the target application.

If you have handbrake on your computer that app is fun to do GUI Script on.

Apple has changed the settings application (possibly based on a Catalyst app) and Applescript (UI-Scripting) has been a horror ever since! Especially when the app needs to be launched, you need to check each UI element beforehand if it exists. Here is an example which works for me:


use framework "Foundation"
use framework "AppKit"
use scripting additions

-- see for ids: https://gist.github.com/rmcdongit/f66ff91e0dad78d4d6346a75ded4b751
current application's NSWorkspace's sharedWorkspace()'s openURL:(current application's NSURL's URLWithString:"x-apple.systempreferences:com.apple.ControlCenter-Settings.extension")

tell application "System Events" to tell application process "System Settings"
	set frontmost to true
	tell window 1
		tell group 1
			tell splitter group 1
				tell group 2
					tell group 1
						tell scroll area 1
							tell group 3
								set timeoutDate to (current date) + 5 -- timeout 5 seconds
								repeat while (current date) < timeoutDate
									set targetUIElement to a reference to checkbox 3  -- toggle battery percent in menu bar
									if targetUIElement exists then
										click targetUIElement
										exit repeat
									end if
									delay 0.1
								end repeat
							end tell
						end tell
					end tell
				end tell
			end tell
		end tell
	end tell
end tell

PS: This is of course how it works in the concrete example -:slight_smile:


do shell script "defaults -currentHost write com.apple.controlcenter BatteryShowPercentage -bool true"
do shell script "defaults -currentHost write com.apple.controlcenter BatteryShowPercentage -bool false"

I’m working on a System Settings library to hide all this ugliness behind. It will take me a bit to wrap all the individual panels full controls this way. So far I have the following functionality complete…

Opening all System Settings panels.
activate_General_Sharing(“Remote Apple Events”) – Enabling all sharing protocols supported.
show_options_General_Sharing(“Remote Apple Events”) – Opening all sharing protocols options panels supported.
open_Accessibility_SubPanel(“shortcut”) – Opening all accessibility sub-panels supported.
open_PrivacySecurity_SubPanel(“contacts”) – Opening all Privacy & Security sub-panels supported.