Change Keyboard Layout AppleScript Stopped Working After Upgrading to Monterey - applescript

I have the AppleScript below that worked great in Big Sur. But after upgrading to Monterey, it stopped working. Can anyone help me fix it?
Thanks!
changeKeyboardLayout("Squirrel")
on changeKeyboardLayout(layoutName)
tell application "System Events"
tell process "TextInputMenuAgent"
click menu item layoutName of menu 1 of menu bar item 1 of menu bar 2
click menu bar item 1 of menu bar 2
end tell
end tell
end changeKeyboardLayout
If I change layoutName to a number, such as 1
click menu item 1 of menu 1 of menu bar item 1 of menu bar 2
ScriptDebugger shows
menu item "U.S." of menu 1 of menu bar item 1 of menu bar 2 of application process "TextInputMenuAgent"
So it is able to get U.S., but the click simulation does not have any effects, i.e., it does not switch the keyboard layouts to U.S. (from another keyboard).

The example AppleScript code, shown below, was tested in Script Editor under macOS Monterey with Language & Region settings in System Preferences set to English (US) — Primary and worked for me without issue1.
1 Assumes necessary and appropriate settings in System Preferences > Security & Privacy > Privacy have been set/addressed as needed.
Example AppleScript code:
my changeKeyboardLayoutTo("U.S.")
to changeKeyboardLayoutTo(layoutName)
ignoring application responses
tell application "System Events" to ¬
click menu bar item 1 of menu bar 2 of ¬
application process "TextInputMenuAgent"
end ignoring
delay 0.1
do shell script "killall 'System Events'"
delay 0.2
tell application "System Events"
launch
click menu item layoutName of menu 1 of ¬
menu bar item 1 of menu bar 2 of ¬
application process "TextInputMenuAgent"
end tell
end changeKeyboardLayoutTo
Notes:
The example AppleScript code assumes one has checked Show Input menu in menu bar in: System Preferences > Keyboard Input Sources
The example AppleScript code is also coded to workaround the ~5 second delay that is a know issue between actuating the primary menu and the the target menu item on the menu.
See my answer A: AppleScript - Can't get rid of delay after click for the reference to mentioned ~5 second delay, which still persists in macOS Big Sur and macOS Monterey. It also includes other methods to click the target menu items that can be adapted as/if needed. Although I have not tested the alternate solutions in macOS Monterey yet.
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

How to reopen all files listed in macOS "recently closed" or "open recent" menu?

Rarely but occasionally, such as after a kernel panic, a macOS application doesn't automatically reopen with previously-open files/windows. In those cases, however, the "Recent" or "Open Recent" menu item almost always has those files or windows listed... but opening all of them can be a chore, clicking one, which then closes the menu, reopening the menu, clicking the next, etc.
Is there any way to more-efficiently open all of the files in that list?
I have tried searching to see if there is any way to select multiple menu items at once and have tried searching for an AppleScript solution, both with no luck.
The following AppleScript solution works in Finder, Preview, and TextEdit. (Change the script's second line as needed.)
It likely works in other applications as well.
--------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2021/10/30 19:17
# dMod: 2021/10/30 19:17
# Appl: Preview, System Events
# Task: Open All Recent Items Listed in the Recent Items Menu.
# Libs: None
# Osax: None
# Tags: #Applescript, #Script, #Preview, #System_Events, #Open, #Recent, #Items
# Test: Tested only on macOS 10.14.6.
--------------------------------------------------------
# User note: This AppleScript works in macOS 12.0.1.
# I have had success using it with Preview, Finder, and TextEdit.
--------------------------------------------------------
tell application "System Events"
tell application process "Preview"
tell menu bar 1
tell menu "File"
tell menu item "Open Recent"
tell menu 1
set recentMenuItems to UI elements whose title is not "Clear Menu" and title is not ""
repeat with menuItem in recentMenuItems
tell menuItem
perform action "AXPress"
end tell
end repeat
end tell
end tell
end tell
end tell
end tell
end tell
--------------------------------------------------------

Need script to click button on website that downloads a file

I am new to this so this is probably a dumb question but....
I am trying to get a download to happen off a website by clicking on a link but I don't think I have my code right for AppleScript.
The script opens the right website, but when I try to get it to download the file I need by clicking "export data" the code below doesnt seem to do anything, and am not sure what I am missing/did wrong. No error code. Just doesnt do anything.
Website Here
to clickId(LeaderBoard1_cmdCSV)
tell application "Safari"
do JavaScript "document.getElementById('" & LeaderBoard1_cmdCSV & "').click();" in document 1
end tell
end clickId
Thanks for the help.
The following example AppleScript code will open a new Safari window to the designated URL, wait for the page to finish loading, then click the Export Data link to download the FanGraphs Leaderboard.csv file.
Note: This was tested on macOS High Sierra, however for macOS Mojave and later there is a note in the waitForPageToFinishLoadingInSafari() handler to modify its code. Don't forget to do it if applicable.
To use JavaScript with AppleScript and Safari the Allow JavaScript from Apple Events on the Safari > Develop menu, which is hidden by default, must be checked. It can be shown by checking [√] Show Develop menu in menu bar in: Safari > Preferences… > Advanced
set theURL to "https://www.fangraphs.com/leaders.aspx?pos=all&stats=bat&lg=all&qual=50&type=c%2c6%2c11%2c12%2c13%2c21%2c23%2c39%2c35%2c34%2c41%2c42%2c43%2c104%2c107%2c110%2c206%2c209%2c211%2c50%2c61&season=2019&month=0&season1=2019&ind=0&team=0&rost=0&age=0&filter=&players=0"
tell application "Safari" to ¬
make new document with properties {URL:theURL}
my waitForPageToFinishLoadingInSafari()
my clickId("LeaderBoard1_cmdCSV")
-- # Handlers:
to clickId(ElementID)
tell application "Safari"
do JavaScript "document.getElementById('" & ElementID & "').click();" in document 1
end tell
end clickId
on waitForPageToFinishLoadingInSafari()
-- # NOTE: For macOS Mojave and later, change 'UI element 1' to 'UI element 2` in the code below.
tell application "System Events"
repeat until (accessibility description of ¬
button 1 of UI element 1 of every group of toolbar 1 of window 1 of ¬
process "Safari" whose name = "Reload this page") contains "Reload this page"
delay 0.5
end repeat
end tell
end waitForPageToFinishLoadingInSafari
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. 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.

Applescript - How to tell application to open a specific menu item

This is my first attempt to create an applescript.
What i'd like to do is create an apple script and then assing a custom shortcut to it so that it is launched when i need it.
I need it to quickly expand Thunderbird's insert -> HTML... menu.
My current applescript is nested into an automator workflow, and the code is the following:
on run {input, parameters}
tell application "Thunderbird"
activate
tell application "System Events"
tell process "Thunderbird"
click menu item 6 of menu 1 of menu bar item "Insert" of menu bar 1
end tell
end tell
end tell
return input
end run
And when i launch it (after grant permissions to automator), this is the error i get:
Syntax error: System Events got an error; Can't get menu bar item
"Insert" of menu bar 1 of process "Thunderbird"
I think that the proble is because the "Insert" menu is only available when the "Write new message" panel is open in thunderbird...
So my question is, how can i change the script above so that instead of only checking for "Thunderbird" app, it checks that both "thunderbird" and it's own "write new message" panel are open?
And also, is it liklely to be for this reason that i get this error, or i made some mistake in my applescript creation?
Thanks a lot and feel free to ask for more details.

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 keep an application activated/in foreground while a script is running?

I'm using Applescript to automate deployment of applications from Xcode 4.
I use System Events to click the menu items in the menu bar for that. I have the whole thing working, but with one quirk. If the user clicks elsewhere while my script is running, that is the XCode 4 window goes out of foreground, my entire script fails. Is there a way to force Xcode to be in the foreground from my script?
Now, if only Xcode 4 was at least as scriptable as Xcode 3, I wouldn't have to resort to GUI automation.
You can just use the activate command for every click call to ensure that the application is in the foreground. It's not ideal. Really if you're going to use System Events for scripting input like this you have to just accept that the user can't really use the computer whilst the script is running!
If you can break the script down into parts that require user input and parts that don't, you could present a dialog to the user saying something like, "Are you ready to continue with the script? You'll have to leave your computer for a while!"
... and then when it's finished, "Feel free to use your computer again now!"
This might make the script a little less obtrusive. Just a suggestion.
you should put up some of loading image or something while it is running also anytime you call a gui you should run a loop with a timeout that activates the app then checks for the existence of the items you want to click then when it exists click it and get out of the loop
EDIT
helpful link
A combination of mcgrailm and James Bedford's answers worked.
I put the menu click for "Edit Schemes…" in a loop until the edit scheme sheet becomes existent.
I also had to activate the application just before I clicked "Run without building".
The code:
tell application id "com.apple.dt.Xcode"
activate
end tell
tell application "System Events"
tell process "Xcode"
repeat until sheet 1 of window 2 exists
click menu item "Edit Scheme…" of menu "Product" of menu bar item "Product" of menu bar 1
tell application "Xcode"
activate
beep
end tell
end repeat
tell sheet 1 of window 2
set destination to pop up button 2 of group 1
click destination
set target to "iPad 4.3 Simulator"
click menu item target of destination's menu 1
set buildConfig to pop up button 3 of group 2
click buildConfig
click menu item "Debug" of menu 1 of buildConfig
click button "OK"
end tell
tell application "Xcode"
activate
beep
end tell
tell application id "com.apple.dt.Xcode"
activate
end tell
click menu item "Run Without Building" of menu 1 of menu item "Perform Action" of menu "Product" of menu bar item "Product" of menu bar 1
end tell
end tell

Resources