Automatically Add Application to Allow assistive access - xcode

Part of an application changes the scroll direction of the trackpad with this AppleScript (used as AppleScriptObjC in Xcode AppleScript application).
When running, it often pops up with a message telling me that my app has not been allowed accessibility access (the usual message...)
Here is the code:
on TrackpadIsAttached()
try
tell application "System Preferences" to quit
tell application "System Preferences"
activate
set current pane to pane "com.apple.preference.trackpad"
end tell
tell application "System Events" to tell application process "System Preferences"
tell radio button 2 of tab group 1 of window 1 to if value is 0 then click
tell checkbox 1 of tab group 1 of window 1 to if value is 1 then click
end tell
tell application "System Preferences" to quit
functionSuccessful("Mouse control optimisation completed successfully.")
on error errMsg
my errorReporting(errMsg, "Fatal Mouse Optimisation (Trackpad) Error")
tell application "System Preferences" to quit
end try
end TrackpadIsAttached
I know I can do it manually with: System Preferences > Security & Privacy > Privacy > Accessibility but can it also be done automatically with AppleScriptObjC or 'Do Shell Script'? - I don't mind if the user has to type is a password to authenticate it etc.
Any help is greatly appreciated.

Two things:
GUI Scripting is the automation option of absolutely last resort: humiliatingly klunky and brittle as hell, and enabling it either manually or automatically opens up a potential security risk—not a liability you want to place on either yourself or your users if you can possibly help it. If there is any programmatic way to perform the operation you need, use that instead. Which leads us to…
You haven't said why your users need and/or want to change their trackpad direction. What is the purpose of your app? Is it intended to give users who frequently reverse trackpad direction (e.g. while playing third-party games) with an easier way to do it? Or it trying to reverse it for its own purposes? (e.g. If your app just needs to know which way the user's finger is really moving, use -[NSEvent isDirectionInvertedFromDevice].)
Update your question to explain your overall goal, and you're a lot more likely to receive robust high-quality answers that won't further dig you into any holes of your own unintended making.

Related

How to click on a button in an app from the status bar with Apple Script

I have see how to click on menu items but this application does not have those. I was wondering how to click on the button Connect
I tried click at {818, 320} but it did not work
Here is the scrip, i was able to open the app with this
tell application "System Events"
tell UI element "Hotspot Shield"
tell menu bar item 1 of menu bar 2
click
delay 2
get the actions of button "Connect"
end tell
end tell
end tell
FWIW One would not normally use tell UI element "Hotspot Shield" rather use tell application process "Hotspot Shield", however, looking at this through Accessibility Inspector, I do not see a way to click the "Connect" button. Even using a Watch Me Do action in Automator, while it will record the process, it won't play it back successfully.
That said, here is a workaround solution that works for me on macOS Mojave using AppleScript and the third-party command line utility Cliclick.
Looking at the cropped screen shot in your OP and using the approximate center of the Connect button to be at 320 for the y axis and using AppleScript to get the position of the menu bar item for use as the approximate x axis, the following example AppleScript code should work for you too.
tell application "System Events" to ¬
tell application process "Hotspot Shield" to ¬
tell menu bar item 1 of menu bar 2
set xPos to first item of (get its position)
click
end tell
delay 0.5
do shell script "/Applications/cliclick c:" & xPos & ",320"
Note that the value of the delay command may need to be adjusted to ensure the Connect button is visible before the click event takes place using cliclick.
Adjust the path to cliclick as needed. I placed it in /Applications just for testing purposes.
The usual caveats, regarding System Preferences > Security & Privacy > Privacy, apply.
I am not affiliated with the developer of Cliclick, just a satisfied user of the product.
Note: The example AppleScript code is just that and does not contain any 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.

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

AppleScript to block Safari pop-up windows

I am trying to automate the blocking of pop-up windows in Safari.
I have tried the following defaults write operation
defaults write com.apple.Safari WebKit2JavaScriptCanOpenWindowsAutomatically -boolean false
But this fails to do it. I have also tried setting it as true but even that didn't help. I am currently trying to find a way to do it using AppleScript.
This is what I have written so far -
CMD_ACTIVATE='tell application "Safari" to activate'
CMD_NEWTAB='tell application "System Events" to keystroke "," using {command down}'
osascript -e "$CMD_ACTIVATE" -e "$CMD_NEWTAB"
This opens up the preferences but then I draw a blank. Anyone with any suggestions on how to proceed? Also I don't really need a solution to this only in AppleScript any other way to do it would also be helpful.
Note: I have been using Mac OS only for a week now, and am not that well versed in the nuances of this OS, so please be a bit descriptive when answering.
Thanks.
Blocking pop-up window is done via Safari / preferences / tab Security where you need to set the correct checkbox.
This preference seems to be stored in your library / preferences file com.safari.plist which contains the flag com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically with value Yes when pop-up are blocked.
However, it may not be the only place to be changed and in any cases, it is not officially documented, so that place can be changed by Apple any time. This is not recommended to use it.
Going back to Applescript, because Safari is quite poor in terms of applescript handling events, you are forced to go via GUI scripting. That’s what you’ve started, but keep in mind that if Apple changes the layout of Safari preference window, your script must be reviewed.
When going through GUI scripting (which, again, should only be when no other solution found) you must understand structure of GUI objects. Window contains button, check box, tool bar... in a hierarchy model. For instance the preference window in Safari contains bellow the tool bar, an object "group 1" with itself contains many objects depending of the tool bar current selection. Once you understand that concept, the script below, which does what you're looking for, will be easy to understand with many comments:
tell application "Safari" to activate
tell application "System Events"
keystroke "," using {command down}
delay 0.2 -- leave sometime to open window
tell window 1 of process "Safari"
click button 6 of toolbar 1 -- Security button is number 6
delay 0.2
-- check if check box not yet set and set it.
if (value of checkbox 5 of group 1 of group 1) = 0 then click checkbox 5 of group 1 of group 1
end tell
delay 0.2
click button 1 of window 1 of process "Safari" -- click on red / close button
end tell
I am running on Safari 10.0.3. If your version is different, the preference window may be different. Then the script must be adjusted: the Security tab button may not longer be the number 6 in your version,...

How do I scroll to the top of a window using applescript?

I want applescript to scroll a window all the way up.
I've tried the page up key, the home key, and I've tried looking for a way to scroll using the built in scrolling capabilities of the window, but I've so far been unable to even move the scrolled position at all.
Basically, use a tell app "System Events" statement to send keystrokes and key codes.
In theory, you could use the following:
keystroke page up key
keystroke page down key
keystroke home key
But for me this doesn´t work. The good news is that you can use the key codes instead. I suggest using the excellent free Full Key Codes application to read them, though it is a bit tricky to let it read two keys pressed simultaneously.
The key codes for the fn+ arrow keys-combos are as following:
Page up: fn+ up key: key code 116
Page down: fn+ down key: key code 121
Home: fn+ left key: key code 115
End: fn+ right key: key code 119
So for example if you had a long page open in Safari, and you want to scroll to its end, use
tell application "System Events"
tell application "Safari" to activate
— to see the animation, we wait a moment:
delay 0.5
key code 119
end tell
With browsers you could also use JavaScript:
tell application "Safari" to tell document 1
do JavaScript "window.scroll(0,0)"
end tell
tell application "Google Chrome" to tell active tab of window 1
execute javascript "window.scroll(0,0)"
end tell
The alternative to sending keystrokes is to use GUI scripting.
Caveat: While GUI scripting is more robust than sending keystrokes for a given version of an application, changes in the application's layout in future versions can break your code.
Also:
GUI scripting requires that access for assistive devices be enabled; enabling requires admin privileges:
up to 10.8, this could be done programmatically, system-wide by executing tell application "System Events" to set UI elements enabled to true (required admin privileges)
Sadly, on 10.9+, this no longer works, and apps must be authorized manually, individually - the system will prompt you on first run (requires admin privileges)
however, in both scenarios tell application "System Events" to get UI elements enabled will report whether access is enabled or not.
Determining the right UI element targets can be non-trivial and tedious; using the Accessibility Inspector utility that comes with Xcode helps. The class names reported by this utility correspond to the UI element classes contained in the System Events dictionary; e.g., AXSplitGroup corresponds to splitter group.
The following scrolls Safari 6.0.3's front window to the top (access for assistive devices must be enabled):
tell application "System Events"
# Use Accessibility Inspector to find the desired target.
tell front window of process "Safari"
tell scroll bar 1 of scroll area 1 of group 1 of group 1 of last group
set value of attribute "AXValue" to 0 # Scroll to top.
end tell
end tell
end tell
Update: As a reminder that this type of scripting works well for a given version of an application, the code had to be changed for Safari 8.0.4:
tell application "System Events"
# Use Accessibility Inspector to find the desired target.
tell front window of process "Safari"
tell scroll bar 1 of scroll area 1 of group 1 of group 1 of group 2
set value of attribute "AXValue" to 0 # Scroll to top.
end tell
end tell
end tell

AppleScript -- How to change the default Printer based on network

I would like to make an application that will run on my computer that will change the "Default Printer" in the "Printers & Fax" Preference Pane of "System Preferences" through AppleScript?
I want it to change the printer based on my wireless network that I am on. I will quit and start with every network change if I have to, but ideally, I would like it to do that automatically for me.
How might I go about doing this? If you need the IP address, network names, and or printer names, leave a comment and let me know. There are 3 printers I want it to switch between and 3 wireless networks I want it to switch between.
Thanks!
Something like this will get you started to grab the current location. You'll need to trigger this when you change the location, and then once it grabs the location, you'll need an if else statement to walk through yoiur different printers. MacScripter is a great place for Applescript help; someone has proabably already done what you want to do: MacScripter. There are also ways to get network location in the shell, which would be faster that Applescript.
And there's MarcoPolo - Context-aware computing for Mac OS X, an app that will do what you want without writing an Applescript.
tell application "System Preferences"
activate
end tell
tell application "System Events"
tell application process "System Preferences"
set frontmost to true
click menu item "Network" of menu "View" of menu bar 1
--you may need a delay here, adjust to suit
delay 1
set machineLocation to value of pop up button 1 of window "Network"
end tell
end tell
tell application "System Preferences" to quit

Resources