The bug:
When AppleScript's progress dialog is succeeded by a dialog, the progress dialog still lingers—even though all progress steps have completed, and the progress bar is full. It will linger until the script has been cancelled, until the script has completed, or until no additional dialogs exist in the script.
This bug cannot be witnessed while running the code from within Script Editor.app, because, in Script Editor, a progress dialog will not appear. Instead, a pie-shaped progress meter is integrated into the bottom of the script window.
How to reproduce the bug:
Save the following AppleScript code as an .app file:
(The file must be an .app file, as .scpt files cannot display progress dialogs.)
set n to 5
set progress total steps to n
set progress description to "Script Progress"
set progress additional description to "Additional description"
repeat with i from 1 to n
delay 0.1
set progress completed steps to i
end repeat
display dialog "The progress dialog should be gone at this point."
Upon launching the application, you will see the following:
The question:
Does a workaround exist to force the progress dialog to close once its complete, so that additional dialogs can be placed after the progress dialog, without having the progress dialog still visible?
What I've tried:
I tried approaching the problem by interpreting the progress dialog simply as a "window" of the app.
If you run the following code in a separate AppleScript file, while both dialogs of ProgressBarTest.app are on screen (as in the above screenshot):
tell application "System Events"
set allWindows to name of window of processes whose visible is true
end tell
return allWindows
you will learn that ProgressBarTest.app has 2 open "windows". The titles of these windows are:
{"", "ProgressBarTest.app"}
The first window in this list refers to the display dialog
dialog. The second window in this list, entitled ProgressBarTest.app
, is the progress dialog.
I then attempted to close this progress dialog "window" by using AppleScript (like one may do for any standard application window). But, the following code:
tell application "System Events" to tell process "ProgressBarTest.app"
if exists window "ProgressBarTest.app" then
close window "ProgressBarTest.app"
end if
end tell
will give the user an error. The text of this error dialog is:
Script Error
System Events got an error: window "ProgressBarTest.app" of process "ProgressBarTest.app" doesn’t understand the “close” message.
I shortly realized that, if your screen is the same point of view as that of the above screenshot, then you cannot even manually close out of the progress dialog. This is because the display dialog
dialog takes precedence over the progress dialog; the display dialog
dialog "grays out" (i.e., disables) all of the buttons in the progress dialog.
So, to account for this, in the ProgressBarTest.app code, I added a delay 5
directly above the display dialog "The progress dialog should be gone at this point."
line. I wanted to see if I could successfully close the progress dialog, if the progress dialog was the only active dialog of the application.
I tried the following code:
tell application "System Events" to tell process "ProgressBarTest.app"
if exists window "ProgressBarTest.app" then
click button 1 of window "ProgressBarTest.app"
end if
end tell
In the above code, button 1
refers to the Stop button that is found in the progress dialog. (You can alternatively use button -4
or button 0
to refer to this same button.)
The good news is that this code successfully closed out of the progress dialog!
The bad news, however, is that when the progress dialog's Stop button is pressed, instead of only the progress dialog being closed, the entire script is cancelled. This is obviously undesirable.
The root of the issue is that the progress dialog contains no red "x"; the left-most circular button in the top bar of this dialog is always grayed-out. In other words, there is no way to close the progress dialog manually, without also prematurely ending the script.
So, this problem is more difficult to solve than I thought.
It appears that my desired outcome is impossible to achieve.
OS X El Capitan, version 10.11.6.
Best Answer
Works for me on latest version of macOS Big Sur
UPDATE
BEST SOLUTION
If you place the
display dialog
command within aSystem Events tell block
then wrap theignoring application responses
command around thatdisplay dialog
command, theprogress indicator
will complete it’s task without waiting for thedisplay dialog
window to be dismissed.The
ignoring application responses
command will only work if it is placed within an application’stell block
OLD SOLUTION 1
Here is a way to run some repeat loops before the script quits
OLD SOLUTION 2
Working on one of my own projects, I had one of those "EUREKA!" moments. Here is a completely different approach than my code in SOLUTION 1. The approach here was to wrap most of my code in script objects or handlers, then call those objects as needed. In this solution, I saved this script as a stay open application, with explicit run and idle handlers. Some of the code runs when the application is launched, but most of the commands actually happen within the idle handler.
I think this solution has more promise than SOLUTION 1.