applescript access switch control through system preferences - macos

My end goal is to click the "Enable Switch Control" checkbox, which can be found under Accessibility-> Switch Control in System Preferences. I have had some trouble getting the applescript to work and would like to find out what is causing the issue.
My current code:
if running of application "System Preferences" then
quit application "System Preferences"
delay 1
end if
tell application "System Preferences"
reveal anchor "Switch" of pane id "com.apple.preference.universalaccess"
activate
end tell
I got the anchor Switch by using:
tell application "System Preferences"
get anchors of pane id "com.apple.preference.universalaccess"
end tell
which returned all of the available anchors. Here is a snippet:
...anchor TextToSpeech of pane id com.apple.preference.universalaccess, anchor Dwell of pane id com.apple.preference.universalaccess, anchor Dictation of pane id com.apple.preference.universalaccess, anchor Switch of pane id com.apple.preference.universalaccess, anchor Siri of pane id com.apple.preference.universalaccess...
I tried testing the applescript with other anchors (Dictation, Siri, etc) and they all worked (directed me to the intended area), but Switch doesn't. I even tried replacing "Switch" with its numerical value, reveal anchor 11 of pane id "com.apple.preference.universalaccess", but that also fails. Why is that? Also, how would I modify the applescript to get the intended result?

There appears to be a bug in that System Preferences will not properly reveal anchor "Switch" of pane id "com.apple.preference.universalaccess" and as such, here is a workaround.
Note that the coding in the example AppleScript code assumes that Switch Control has once previously been turned on manually so as to answer the initial System Preferences is trying to unlock Accessibility preferences dialog box where you have entered your User Name and Password then clicked the Unlock button.
The example AppleScript code, shown below, was tested in Script Editor under macOS Catalina and macOS Big Sur with Language & Region settings in System Preferences set to English (US) — Primary and worked for me without issue to click the Enable Switch Control checkbox.1
1 Assumes necessary and appropriate settings in System Preferences > Security & Privacy > Privacy have been set/addressed as needed.
and works for me to click the Enable Switch Control checkbox:
-- # Check to see if System Preferences is
-- # running and if yes, then close it.
-- #
-- # This is done so the script will not fail
-- # if it is running and a modal sheet is
-- # showing, hence the use of 'killall'
-- # as 'quit' fails when done so, if it is.
-- #
-- # This is also done to allow default behaviors
-- # to be predictable from a clean occurrence.
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
-- # Make sure System Preferences is not running before
-- # opening it again. Otherwise there can be an issue
-- # when trying to reopen it while it's actually closing.
repeat while running of application "System Preferences" is true
delay 0.1
end repeat
-- # Open System Preferences to the Accessibility pane.
tell application "System Preferences" to ¬
reveal pane id "com.apple.preference.universalaccess"
-- # Use System Events to achieve the goal.
tell application "System Events"
tell window 1 of application process "System Preferences"
-- # Wait for target pane to be available.
-- # The target in this case has a checkbox.
my waitForUIelement(checkbox 1)
-- # Ascertain the target row to select.
set rowSwitchControl to the first row of ¬
table 1 of scroll area 1 whose value of ¬
static text 1 of UI element 1 is ¬
"Switch Control"
-- # Select the target row.
select rowSwitchControl
-- # Wait for target checkbox to be available.
my waitForUIelement(checkbox 1 of tab group 1 of group 1)
-- # Click the Enable Switch Control checkbox.
click checkbox 1 of tab group 1 of group 1
end tell
end tell
delay 0.02
quit application "System Preferences"
-- ## Handler(s) ##
on waitForUIelement(uiElement)
tell application "System Events"
tell window 1 of application process ¬
"System Preferences"
set i to 0
repeat until exists uiElement
delay 0.1
set i to i + 1
if i ≥ 30 then return
end repeat
end tell
end tell
end waitForUIelement
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.

Related

What terminal command can I use to terminate the cursor/mouse process on a MacOSX?

What terminal command can I use to terminate the cursor/mouse process on a MacOSX?
I'm changing the size of the mouse using another command in the terminal and now I need to restart the process that displays the cursor. I have searched for hours for a similar topic, but couldn't find one.
Does anybody know how to achieve this?
If by "changing the size of the mouse using another command in the terminal", you mean that you set the System Preferences value (i.e. using 'defaults' command), then you could either log out and log back in, or it may be a bit tedious -- see this answer: How to programatically change the cursor size on a Mac
If all you need to do is to change a mouse cursor size system-wide, you can use UI scripting (as suggested in the answer I linked). The command to execute would be:
osascript -e '
tell application "System Preferences"
reveal anchor "Seeing_Display" of pane id "com.apple.preference.universalaccess"
end tell
tell application "System Events"
set theSlider to slider "Cursor size:" of group 1 of window 1 of application process "System Preferences"
set stash to value of theSlider
set value of theSlider to SIZE_OF_THE_CURSOR
stash
end tell'
Note that you need to "enable assistive access" to osascript:
http://jacobsalmela.com/bash-script-enable-access-assistive-devices-programmatically-os-x-mavericks-10-9-x-simulate-keystrokes/
"is not allowed for assistive access" error when running AppleScript from Java

Applescript - Close Pages Document Automatically

I am trying to create a script that will automatically close the frontmost window of Apple Pages.
on run {}
tell application "System Events"
if (window 1 of process "Pages" exists) then
try
tell application "Pages"
--display dialog "Hello World!" --TODO: remove, test code only.
--Keywords I have tried: file, document, window,
close window 1 saving no
end tell
--close window 1 of process "Pages" saving no
on error errMsg
display dialog "ERROR: " & errMsg
end try
end if
end tell
end run
Whenever I run this, it gives me the following error:
ERROR: Pages got an error: window 1 doesn’t understand the “close”
message.
I have looked at this article, and have used the following command:
sudo defaults write /Applications/Pages.app/Contents/Info NSAppleScriptEnabled -bool YES
However, it still fails to work. Any advice?
Details:
System Version: OS X 10.9.1 (13B42)
Kernel Version: Darwin 13.0.0
Pages: 5.0.1
If Pages isn't scriptable, you're kind of out of luck. If it were scriptable, you wouldn't need System Events to close a window; that kind of functionality is usually included in a scriptable app's dictionary.
System Events can help with apps that aren't scriptable, but you have to rely on the actual UI. But if that's the solution, you can't use tell application "Pages" for the inner block (like you have it); you have to use:
tell process "Pages"
If you go that route, now you have to use either the close button on window 1 or use the close menu command. Something like:
activate application "Pages"--note that this will probably be NECESSARY (if it's not frontmost, it prob won't work)
tell application "System Events"
tell process "Pages"
click menu item "Close" of menu "File" of menu bar item "File" of menu bar 1 of it
end tell
end tell
BUT then you have to come up with the problem of what happens if the window hasn't been saved (has been modified) -- which in a scriptable app uses the construction you were originally trying. When using System Events, you can do:
activate application "Pages"--note that this will probably be NECESSARY (if it's not frontmost, it prob won't work)
tell application "System Events"
tell process "Pages"
click menu item "Close" of menu "File" of menu bar item "File" of menu bar 1 of it
delay .5
keystroke "d" using command down
end tell
end tell
But then again how do you make the script smart enough to know if the window has been modified or not? Or maybe you use System Events to see if the window has been killed after the close command, and if it hasn't, it does the keystroke thing. This kind of thing can be done by doing something like:
activate application "Pages"
tell application "System Events"
tell process "Pages"
set frontMostWinName to name of window 1
click menu item "Close" of menu "File" of menu bar item "File" of menu bar 1 of it
tell me to delay 0.5
if exists window 1 then
if name of window 1 = frontMostWinName then keystroke "d" using command down
end if
end tell
end tell
I don't have Pages, but this works with another non-scriptable app, Bean (although I should mention that Bean uses tabs, and I had to move a tab to a window to get this to work*, and I don't know how Pages works in this regard).
[EDIT: *actually, this is not true; this works in Bean regardless of tabs/windows]

How to use applescript to toggle the language setting of new dictation tool (10.8)

I really like the new dictation feature of MacOSX Mountain Lion. I am using it in two languages; english (u.s.) and french.
Each time I need to switch language, I have to go in system preference, Dictation and Speech, and select the language.
Now, I would like use Applescript to do that automatically , unfortunately, since it is so new, I cannot get the proper string of dictation module.
Quick example (this is just a start):
tell application "System Preferences"
activate
set the current pane to pane id "com.apple.preference.xxxxxx"
end tell
for xxxx I tried "Dictation&Speech" a wild guess that did not work.
Any ideas on how I can get the exact string for "Dictation & Speech" ?
Thank in advance,
François
To get the id of a pane : go in system preference, select a pane, run this script in the Editor.
tell application "System Preferences" to get id of current pane
The result is the exact string.
You could either edit property lists that store the setting and reopen the DictationIM process:
#!/bin/bash
k="com.apple.speech.recognition.AppleSpeechRecognition.prefs DictationIMLocaleIdentifier"
if [[ "$(defaults read $k)" == en-US ]]; then
defaults write $k fr-FR
defaults write com.apple.assistant "Session Language" fr-FR
else
defaults write $k en-US
defaults write com.apple.assistant "Session Language" en-US
fi
killall -HUP DictationIM
Or use UI scripting:
delay 0.3 -- time to release modifier keys if the script is run with a shortcut
tell application "System Preferences"
reveal anchor "Dictation" 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
click
if value is "English (United States)" then
click menu item "French" of menu 1
else
click menu item "English (United States)" of menu 1
end if
end tell
end tell
quit application "System Preferences"
Cool stuff!
If you have 'Notifications Scripting' installed ( http://www.cooperative-fruitiere.com/notifications/index_en.html ), then you can even have a notification informing you about the language.
And by the help of FastScripts, you can assign a keyboard shortcut to this script.
-- Switch the language of Mountain Lion's dictation
-- Here, we just toggle between English and German
-- Needs 'Notifications Scripting' ( http://www.cooperative-fruitiere.com/notifications/index_en.html )
delay 0.3 -- time to release modifier keys if the script is run with a shortcut
tell application "System Preferences"
reveal anchor "Dictation" 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
click
if value is "English (United States)" then
set language to "German (Germany)"
else
set language to "English (United States)"
end if
click menu item language of menu 1
end tell
end tell
quit application "System Preferences"
tell application "Notifications Scripting"
set event handlers script path to (path to me)
-- The user info parameter is a record. The supported data types are text, integer, real, boolean, date, alias, file and POSIX file.
set dict to {theName:"Notifications Scripting", theVersion:"1.0", theScript:event handlers script path}
display notification "Dictation Language" subtitle "Switched to:" message language
end tell
using terms from application "Notifications Scripting"
-- This handler is called when a notification was delivered.
on notification delivered title aTitle subtitle aSubTitle message aMessage actual delivery date aDeliveryDate user info aDict
end notification delivered
end using terms from
The script provided doesn't work unless you put in a delay command. Also, it needs to be application process, not simply process. Instead of explaining where to make the changes, I'll just post the working code. [Please note, this was tested on macOS Catalina. If apple changes the System Preferences GUI in future versions, this code may not work.]
tell application "System Preferences"
reveal anchor "Dictation" of pane "com.apple.preference.speech"
end tell
delay 1
tell application "System Events" to tell application process "System Preferences"
tell pop up button 1 of tab group 1 of window 1
click
if value is "English (United States)" then
click menu item "Hungarian (Hungary)" of menu 1
else
click menu item "English (United States)" of menu 1
end if
end tell
end tell
quit application "System Preferences"
I now use Alfred to trigger this bash script. I assigned a hotkey to it and replicated it for the languages I speak, so I have three different keyboard shortcuts for my three languages. It uses a slightly modified script to the ones above (with a different pref, no longer requires delays, and immediately triggers dictation.)
k="com.apple.speech.recognition.AppleSpeechRecognition.prefs DictationIMNetworkBasedLocaleIdentifier"
if [ "$(defaults read $k)" != "de_DE" ]
then
defaults write $k "de_DE"
defaults write com.apple.assistant "Session Language" "de_DE"
killall -HUP DictationIM
-- Somehow I need to do twice the keyboard shortcut to start the dictation. This is the first one.
osascript -e 'tell app "System Events" to key code {63,63}'
fi
-- second one
osascript -e 'tell app "System Events" to key code {63,63}'

Script for adding new KeyboardShortcuts on MacOs (Leopard)

Is it possible to add KeyboardShortcuts in MacOs (Leopard) using shell or other programmatic way? Basically, something to automate the steps of opening Keyboard&Mouse in SystemPreferences, selecting the last tab "KeyboardShortcuts", Clicking "+" to add a new one and filling the info.
Thank you
The following AppleScript should do the trick, with 3 variables:
app_name: name of an application that you want to assign the shortcut to, e.g. Safari
menu_title: exact menu name to execute
keystrokes: the actual shortcut
tell application "System Preferences"
activate
set current pane to pane "com.apple.preference.keyboard"
end tell
tell application "System Events"
tell process "System Preferences"
tell window "Keyboard"
click button 3 of tab group 1
tell sheet 1
click pop up button 1
click last menu item of menu 1 of pop up button 1
keystroke "/Applications/" & app_name & ".app"
keystroke return
keystroke return
delay 1
keystroke menu_title
keystroke tab
keystroke last item of keystokes using rest of reverse of keystokes
delay 1
click button "Add"
end tell
end tell
end tell
end tell
The code is referencing the following site:
http://www.rngtng.com/2010/10/29/applescript-to-create-keyboard-shortcuts/

How to start/stop Internet Sharing using AppleScript

I don't have a Wi-Fi router, so when at home I need to turn my laptop into a Wi-Fi source so that both myself and my partner can access the internet.
However during the days I work at a coffee shop and require the use of their Wi-Fi.
I'm running Snow Leopard and I find it stupidly cumbersome to constantly be turning off and on, first Internet Sharing and then my Wi-Fi.
Any ideas for a quick 'n' dirty AppleScript solution?
You can use launchctl to programmatically start or stop the Internet Sharing service.
The following AppleScript will start Internet Sharing:
do shell script "/bin/launchctl load -w /System/Library/LaunchDaemons/com.apple.InternetSharing.plist" with administrator privileges
The following AppleScript will stop Internet Sharing:
do shell script "/bin/launchctl unload -w /System/Library/LaunchDaemons/com.apple.InternetSharing.plist" with administrator privileges
I'm using this AppleScript from Automator so that I can easily use it as a service and give it a keyboard shortcut.
Toggle Internet Sharing:
register_growl()
try
if isRunning("InternetSharing") then
do shell script "launchctl unload -w /System/Library/LaunchDaemons/com.apple.InternetSharing.plist" with administrator privileges
if isRunning("InternetSharing") then
error "Internet Connection Sharing was Not Disabled"
else
my growlnote("Success", "Internet Connection Sharing Disabled")
end if
else
do shell script "launchctl load -w /System/Library/LaunchDaemons/com.apple.InternetSharing.plist" with administrator privileges
if isRunning("InternetSharing") then
my growlnote("Success", "Internet Connection Sharing Enabled")
else
error "Internet Connection Sharing was Not Enabled"
end if
end if
on error errMsg
my growlnote("Error", errMsg)
end try
on isRunning(processName)
try
return 0 < length of (do shell script "ps ax | grep -v grep | grep " & processName)
on error
return false
end try
end isRunning
on register_growl()
try
tell application "GrowlHelperApp"
set the notificationsList to {"Success", "Warning", "Error"}
register as application "Toggle Internet Connection Sharing" all notifications notificationsList default notifications notificationsList icon of application "Sharing"
end tell
end try
end register_growl
on growlnote(growltype, str)
try
tell application "GrowlHelperApp"
notify with name growltype title growltype description str application name "Toggle Internet Connection Sharing"
end tell
end try
end growlnote
I am cross-posting this on the Apple stack exchange because the question was asked in both places.
Not sure if you are still looking for a solution but... here is an apple script to enable or disable internet sharing
tell application "System Preferences"
activate
reveal (pane id "com.apple.preferences.sharing")
end tell
tell application "System Events"
tell process "System Preferences"
try
click checkbox of row 11 of table 1 of scroll area of group 1 of window "Sharing"
if checkbox of row 11 of table 1 of scroll area of group 1 of window "Sharing" is equal to 1 then
repeat until sheet of window 1 exists
delay 0.5
end repeat
end if
if (sheet of window 1 exists) then
click button "Start" of sheet of window 1
end if
tell application "System Preferences" to quit
activate (display dialog "Internet Sharing preferences sucessfully flipped")
on error
activate
display dialog "something went wrong in automation but you are probably in the right menu..."
return false
end try
end tell
end tell
I also will post this on the apple stack exchange post.
Here's what I came up with for Mojave to toggle Internet Sharing using (mostly) accessibility — unfortunately none of the solutions involving using launchctl and/or editing com.apple.nat.plist worked for me.
open location "x-apple.systempreferences:com.apple.preferences.sharing?Internet"
tell application "System Events"
tell process "System Preferences"
repeat until window "Sharing" exists
delay 0.1
end repeat
tell window "Sharing"
set _row to group 1's scroll area 1's table 1's first row whose selected is true
set _wasSharing to _row's checkbox's value as number
if _wasSharing is 1 then
click _row's checkbox
set _wasSharing to _row's checkbox's value as number
repeat until _wasSharing is 0
delay 0.1
end repeat
end if
if _wasSharing is 0 then
click _row's checkbox
repeat until sheet 1 exists
delay 0.1
end repeat
click sheet 1's button "Start"
end if
end tell
end tell
end tell
tell application "System Preferences" to quit

Resources