AppleScript - How do I detect if a specific button is clicked on GUI and terminate the script? - user-interface

I have a script that manipulates a GUI. At some point in the process, a progress indicator appears in the GUI for a few mins. If the user clicks the GUI button button "Stop" of sheet 1 (so not a dialog button), I'd like the script to display dialog followed by error number -128. How do I do this? Here's what I tried...
repeat while progress indicator 1 of sheet 1 exists
try
set button_returned to button returned of button "Stop" of sheet 1
if button_returned is "Stop" then
display dialog "Operation cancelled"
error number -128
end if
end try
end repeat
Note: I use repeat while progress indicator 1 of sheet 1 exists to pause the script whilst the progress indicator is up.

Save this example as usual app to see the correct workaround to solve your problem:
global itemCount
set processName to name of current application
set theList to {"Marlow", "Maddie", "Sammy", "Stuey", "Jessie", "Tolstoy", "Marlow", "Maddie", "Sammy", "Stuey"}
set itemCount to count of theList
set progress total steps to count of theList
repeat with i from 1 to itemCount
set thisItem to item i of theList
set progress description to "Item " & i & " of " & itemCount
set progress additional description to thisItem
-- The delay is simply to simulate processing time
-- so you can see the progress bar in action.
-- Exclude this from your code and put your real do stuff.
delay 1
set progress completed steps to i
end repeat
on quit
if progress completed steps < itemCount then
display dialog "Operation cancelled"
end if
end quit

Related

Pressing cancel in choose from list will cause a error

When I execute this script, everything works fine, but then when I press the cancel button, the script just give me a error, "Can’t get item 1 of false"
set mailList to {"Hide Applications", "Quit Applications", "Full Volume"}
set mailType to choose from list mailList
if item 1 of mailType is "Hide Applications" then
tell application "Finder"
set visible of every process whose visible is true and name is not "Finder" to false
set the collapsed of windows to true
end tell
else if item 1 of mailType is "Full Volume" then
set volume output volume 100
else if item 1 of mailType is "Quit Applications" then
tell application "System Events" to set the visible of every process to true
set white_list to {"Finder"}
try
tell application "Finder"
set process_list to the name of every process whose visible is true
end tell
repeat with i from 1 to (number of items in process_list)
set this_process to item i of the process_list
if this_process is not in white_list then
tell application this_process
quit
end tell
end if
end repeat
on error
tell the current application to display dialog "An error has occurred!" & return & "This script will now quit" buttons {"Quit"} default button 1 with icon 0
end try
end if
You add a check if mailType is a boolean which would happen if you press cancel. The check would be inserted between line 2 and 3 and would look something like this:
...
if class of mailType = boolean then return
...
choose from list returns boolean false when the Cancel button is pressed.
Just abort the script immediately in this case
set mailType to choose from list mailList
if mailType is false then return

Why does this Applescript cause "Export Library.scpt: execution error: System Events got an error: Can’t get process "i". (-1728)"?

ƒIt's caused when run through osascript from terminal using the command line "osascript Export\ Library.scpt /Users/bryandunphy/Development/iTunesLibraryConsolidator testing.xml".
same script as my last (solved) question but posting it's entirety this time.
-- `menu_click`, by Jacob Rus, September 2006
--
-- Accepts a list of form: `{"Finder", "View", "Arrange By", "Date"}`
-- Execute the specified menu item. In this case, assuming the Finder
-- is the active application, arranging the frontmost folder by date.
on menuClick(mList)
local appName, topMenu, r
-- Validate our input
if mList's length < 3 then error "Menu list is not long enough"
-- Set these variables for clarity and brevity later on
set {appName, topMenu} to (items 1 through 2 of mList)
set r to (items 3 through (mList's length) of mList)
-- This overly-long line calls the menu_recurse function with
-- two arguments: r, and a reference to the top-level menu
tell application "System Events" to my menuClickRecurse(r, ((process appName)'s ¬
(menu bar 1)'s (menu bar item topMenu)'s (menu topMenu)))
end menuClick
on menuClickRecurse(mList, parentObject)
local f, r
-- `f` = first item, `r` = rest of items
set f to item 1 of mList
if mList's length > 1 then set r to (items 2 through (mList's length) of mList)
-- either actually click the menu item, or recurse again
tell application "System Events"
if mList's length is 1 then
click parentObject's menu item f
else
my menuClickRecurse(r, (parentObject's (menu item f)'s (menu f)))
end if
end tell
end menuClickRecurse
-- Created by Bryan Dunphy during January of 2017
--
-- select the folder "directory" in Window "WinName" of Application "appName" and then clicks the default button if requested
-- if WinName is "" then it uses the frontmost window (to allow for unnamed windows)
-- REQUIRES "on handleDir" and "on findRoot" to work!
-- ONLY call switchDir
-- "createIt" is a boolean that will create any missing directories if it is set to "true".
-- "selectDefault" is a boolean indicating whether or not to click the window's default button after selecting the specified directory
-- returns "true" or "false" to indicate success.
-- clicks "Cancel" button on failure
-- Always returns "true" if "createIt" is set to "true"
on switchDir(directory, winName, appName, createIt, selectDefault)
local dirs, delim
set delim to AppleScript's text item delimiters
set AppleScript's text item delimiters to "/"
set dirs to every text item of directory
tell application "System Events" to tell process appName to set frontmost to true
my findRoot(appName, winName)
repeat with dir in dirs
if not handleDir(dir, winName, createIt) then
tell application "System Events" to tell process appName to tell button "Cancel" to click
return false
end if
end repeat
if selectDefault then keystroke return
return true
end switchDir
on handleDir(dir, winName, appName, createIt)
local foundIt
foundIt = false
local ndx
if winName is not "" then
repeat with ndx from 1 to (count of window winName's list 1)
if window winName's list 1's item ndx's value is equal to dir then
select window winName's list 1's item ndx
foundIt = true
exit repeat
end if
end repeat
else
repeat with ndx from 1 to (count of front window's list 1)
if front window's list 1's item ndx's value is equal to dir then
select front window's list 1's item ndx
foundIt = true
exit repeat
end if
end repeat
end if
if not foundIt then
if createIt then
if winName is not "" then
tell application "System Events" to tell process appName to tell window winName
tell button "New Folder"
click
repeat until window "New Folder" exists
delay 0.5
end repeat
set value of text field 1 of window "New Folder" to dir
tell button "Create" to click
return my handleDir(dir)
end tell
end tell
else
tell application "System Events" to tell process appName to tell its front window
tell button "New Folder"
click
repeat until window "New Folder" exists
delay 0.5
end repeat
set value of text field 1 of window "New Folder" to dir
tell button "Create" to click
return my handleDir(dir)
end tell
end tell
end if
end if
else
return foundIt
end if
end handleDir
on findRoot(appName, winName)
local rootName
if winName is not "" then
tell application "System Events" to tell process appName to tell window winName
tell pop up button 1
click
repeat until menu 1 exists
delay 0.5
end repeat
local ndx
repeat with ndx from 1 to (count of menu 1)
if the title of menu 1's menu item ndx is "" then
set rootName to the title of menu 1's menu item (ndx - 1)
select (menu 1's menu item (ndx - 1))
exit repeat
end if
end repeat
end tell
end tell
else
tell application "System Events" to tell process appName's front window
tell pop up button 1
click
repeat until menu 1 exists
delay 0.5
end repeat
local ndx
repeat with ndx from 1 to (count of menu 1)
if the title of menu 1's menu item ndx is "" then
set rootName to the title of menu 1's menu item (ndx - 1)
select (menu 1's menu item (ndx - 1))
exit repeat
end if
end repeat
end tell
end tell
end if
return rootName
end findRoot
on run (clp)
if clp's length is not 2 then error "Incorrect Parameters"
local destination, libraryName
set destination to clp's item 1
set libraryName to clp's item 2
menuClick("iTunes", "File", "Library", "Export Library…")
set value of parentObject's text field "Save As:" to (libraryName and ".xml")
tell pop up button 1 of group 1 of window "New iTunes Library" of process iTunes of application "System Events" to click
repeat with ndx from 1 to (count of parentObject's menu 1)
if title of menu item ndx is "" then
select menu item (ndx - 1)
exit repeat
end if
end repeat
my switchDir(destination, "iTunes", "iTunes", true, false)
set the value of text field "Save As:" of window "iTunes" to (libraryName + ".xml")
tell button "Save" of window "iTunes" to click
return (destination and "/" and libraryName and ".xml")
end run
Change:
menuClick("iTunes", "File", "Library", "Export Library…")
to:
menuClick({"iTunes", "File", "Library", "Export Library…"})
AppleScript's error reporting is truly awful (no tracebacks, for starters), and osascript is even worse than Script Editor for debugging. If you run the script in SE, it will at least highlight the line in your script where the error occurred. If that doesn't give you a clue, add log commands to report the script's progress. osascript will write logged messages to stderr. In SE, click the awful 'document' (show/hide log) icon at the bottom of the window, then select 'Messages'. If your time is worth more than $100, get yourself a copy of Script Debugger which also lets you add breakpoints and step through and inspect variables as the script runs.

Applescript Progress Bar Freezes at end and stays active while next routine is called

I am making an Applescript that automates my local development workflow. Whats happening is I'm using an Applescript progress bar to run while I check for script dependencies (i.e. MAMP). The progress bar appears, animates perfectly, and is returning my routines that check for dependencies as expected. The problem is, even when the progress bar reaches its total steps count, the progress bar freezes, even when the script calls a dialog box in the following routine, and the script freezes.
Here is the routine that starts the progress bar:
on dependency_check()
set progress description to "Access Granted: "
set progress additional description to "Preparing..."
delay 0.5
set progress total steps to 100
repeat with i from 0 to 100
try
if i = 0 then
set progress additional description to "Checking Dependencies..."
delay 0.5
else if (i > 0 and i < 10) then
set progress additional description to "Checking Node.js..."
else if i = 10 then
set progress additional description to node_exists()
else if (i > 10 and i ≤ 20) then
set progress additional description to "Node.js is installed..."
else if (i > 20 and i < 30) then
set progress additional description to "Checking mamp-cli..."
else if i = 30 then
set progress additional description to mampcli_exists()
else if (i > 30 and i ≤ 40) then
set progress additional description to "mamp-cli is installed..."
else if (i > 40 and i < 50) then
set progress additional description to "Checking MAMP..."
else if i = 50 then
set progress additional description to mamp_exists()
else if (i > 50 and i ≤ 60) then
set progress additional description to "MAMP is installed..."
else if (i > 60 and i < 70) then
set progress additional description to "Checking Google Chrome..."
else if i = 70 then
set progress additional description to chrome_exists()
else if (i > 70 and i ≤ 80) then
set progress additional description to "Google Chrome is installed..."
else if (i > 80 and i < 100) then
set progress additional description to "All Dependencies Found..."
else if i = 100 then
set progress additional description to "Complete..."
set progress completed steps to i
end if
set progress completed steps to i
delay 0.025
on error errTxt number errNum -- errTxt and errNum are returned from system
display dialog errTxt & return & errNum
exit repeat
end try
end repeat
end dependency_check
It should be noted that it is calling other routines at i = 10, 30, 50, 70.
They all return text if the dependency is found.
Here is an example of one of those routines:
on node_exists()
set nodeExists to do shell script "test -e /usr/local/bin/node"
if nodeExists is not "" then -- Verifies Node.js is installed by 'test' command
beep
tell application "Finder" to display dialog ¬
"Node.js is not installed, and is needed to run this program. Download Node.js and try again." with title ¬
"Required Library Missing: Node.js!" with icon caution ¬
buttons {"Download Node.js", "Quit Program"} ¬
default button 2 cancel button 2
if button returned of result is "Download Node.js" then
open location "https://nodejs.org/en/"
script_exit()
end if
else
return "Node.js is installed..."
end if
end node_exists
Thanks for any help in advance. I'm completely stuck!

Set a camera in quicktime using applescript

I know there is probably a very simple answer to this. I'm trying to setup an Applescript application that when activated will launch quicktime, open a new movie recording, set the camera and audio, start the recording and then end the recording and save it after 30 seconds.
I currently have a script that is doing everything except setting the camera and audio source. Any tips on how to select a certain camera and audio source using applescript?
Thanks!
Here is the code as it stands now..
--Set some Variables
--Max length of recording
set maxrec to 20 --in seconds
--Ending Message
set EndMsg to "Thank you for participating in this project. Your video has been recorded."
--Begin Loop
repeat
--Get the person's name
repeat
display dialog "What's your name?" default answer ""
set theName to (text returned of result)
if theName ≠ "" then exit repeat
end repeat
--Set the date
set theDate to current date
set y to text -4 thru -1 of ("0000" & (year of theDate))
set m to text -2 thru -1 of ("00" & ((month of theDate) as integer))
set d to text -2 thru -1 of ("00" & (day of theDate))
set h to text -2 thru -1 of ("00" & (hours of theDate))
set mm to text -2 thru -1 of ("00" & (minutes of theDate))
set dateStamp to (y & "-" & m & "-" & d & " " & h & mm as string)
--Create a folder for the person
tell application "Finder"
set p to path to movies folder from user domain
try
make new folder at p with properties {name:"Video Clips"}
end try
set p to (path to movies folder from user domain as text) & "Video Clips:"
make new folder at p with properties {name:dateStamp & " " & theName}
set thePath to result
--Establish the final name of the movie
set fileName to ((thePath as text) & dateStamp & ".mov" as string)
end tell
--Open New Recording, start and stop it
tell application "QuickTime Player"
set newMovieRecording to new movie recording
set windowID to id of first window whose name = "Movie Recording"
delay 2
tell newMovieRecording
--Set Camera to Blackmagic
set current camera of newMovieRecording to Blackmagic of video recording devices
start
end tell
set theSeconds to maxrec
repeat theSeconds times
display dialog theSeconds buttons {} giving up after 1 with title "REMAINING TIME"
set theSeconds to (theSeconds - 1)
end repeat
tell newMovieRecording
stop
end tell
--save and close the recording
set newMovieRecordingDoc to first document whose name = (get name of first window whose id = windowID)
tell newMovieRecordingDoc to save in fileName
set SavedRecordingDoc to first document whose name = (get name of first window whose id = windowID)
tell SavedRecordingDoc to close
quit
end tell
--Display "Thank You" Message
tell application "System Events" to set frontmost of process "Video Booth" to true
display dialog EndMsg giving up after 20 buttons {"Continue…"} ¬
default button 1
end repeat
Here is the error I get right now when I run it.
error "QuickTime Player got an error: Can’t make Blackmagic of every video recording device of document \"Movie Recording\" into type specifier." number -1700 from Blackmagic of every video recording device of document "Movie Recording" to specifier
use the current camera and current microphone properties of your movie recording object. Just replace item 1 with the appropriate device:
set current camera of recording to item 1 of video recording devices
set current microphone of recording to item 1 of audio recording devices
I had accomplished this by doing it manually
tell application "System Events" to tell process "QuickTime Player"
#To open dialog to show available cameras
click button 3 of window 1
#To select our device
click menu item "your_camera_name" of menu 1 of button 3 of window 1
end tell
With this the dialog will open and you will select your camera from the list...
Taken from another answer I made:
https://stackoverflow.com/a/45454785/3685973

The variable result is not defined AppleScript

I am working on the same app that I mentioned in my first question. I have gotten much farther, but when I try to play "2048" the first time, AppleScript give me the error:
"The variable result is not defined"
I will skip the main bulky body of the app and get to the area with the problem:
display dialog "What would you like to do?
Sleep = Go to sleep
Finder = Open Finder
Time = Display current time and date
2048 = play 2048
Quit = Quit application" default answer "" with title "Control panel"
if the text returned of the result is "Sleep" then
tell application "System Events" to sleep
display dialog "Hello, welcome back!" buttons {"Thank you!"} default button 1
return
else if the text returned of the result is "Finder" then
tell application "Finder" to make new Finder window
else if the text returned of the result is "Time" then
set a to (current date) as list
set AppleScript's text item delimiters to linefeed
set a to a as text
display dialog a buttons {"OK"} default button 1
else if the text returned of the result is "Quit" then
return
else if the text returned of the result is "2048" then
tell application "Terminal"
do script "/Users/student/Documents/2048.sh"
activate
end tell
else
display dialog "Invalid response" with title "Invalid response" buttons {"Go back", "Quit"} default button 1
end if
if the button returned of the result is "Go back" then
display dialog "What would you like to do?
Sleep = Go to sleep
Finder = Open Finder
Time = Display current time and date
2048 = play 2048
Quit = Quit application" default answer "" with title "Control panel"
else
return
end if
if the text returned of the result is "Sleep" then
tell application "System Events" to sleep
display dialog "Hello, welcome back!" buttons {"Thank you!"} default button 1
return
else if the text returned of the result is "Finder" then
tell application "Finder" to make new Finder window
else if the text returned of the result is "Time" then
set a to (current date) as list
set AppleScript's text item delimiters to linefeed
set a to a as text
display dialog a buttons {"OK"} default button 1
else if the text returned of the result is "Quit" then
return
else if the text returned of the result is "2048" then
tell application "Terminal"
do script "/Users/student/Documents/2048.sh"
activate
end tell
end if
Just set the result of the display dialog to a variable and use the variable. It's tricky to use "result" as you have in many if statements. One of them is bound to cause a problem because "result" will change at some point.
So do something like this right after your display dialog statement...
set {buttonReturned, textReturned} to {button returned of result, text returned of result}
Then in your if statements use buttonReturned or textReturned.

Resources