Occasionally I need to open an app (e.g. TextEdit) in a script and to momentarily pause operation of the script until the app quits. Right now I use the script shown below but I wondered if there might be a better way that avoids the repeat loop. I have also used System Events to see if TextEdit exists as a process but, once again, this involves a repeat loop. I googled this but could find nothing of help. Thanks.
tell application "TextEdit"
activate
end tell
repeat
if application "TextEdit" is not running then exit repeat
delay 0.5
end repeat
say "OK"
You made the wrong test.
Run this slightly modified version ( the original one entered an infinite loop ) for see:
tell application "TextEdit"
activate
end tell
repeat with i from 1 to 20
log "pass " & i
if (application "TextEdit" is not running) then exit repeat
delay 0.5
end repeat
say "OK"
The events log will be:
[format]tell application “TextEdit”
activate
end tell
(pass 1)
(pass 2)
(pass 3)
(pass 4)
(pass 5)
(pass 6)
(pass 7)
(pass 8)
(pass 9)
(pass 10)
(pass 11)
(pass 12)
(pass 13)
(pass 14)
(pass 15)
(pass 16)
(pass 17)
(pass 18)
(pass 19)
(pass 20)
tell current application
say “OK”
end tell
[/format]
It’s logical because the app is already running when you enter the loop.
This one make the correct test and you will see that it exit the loop before executing it one time so, you may put a delay of 10 hours it will not wait.
tell application "TextEdit"
activate
end tell
repeat with i from 1 to 20
log "pass : " & i
if (application "TextEdit" is running) then exit repeat
delay 0.1
end repeat
say "OK"
Now you may be sure that
tell application "TextEdit"
activate
end tell
repeat
if (application "TextEdit" is running) then exit repeat
say "Beurk, I must wait"
end repeat
will not waste your time.
Of course you may use :
tell application "TextEdit"
activate
end tell
repeat while (application "TextEdit" is not running)
say "Beurk, I must wait"
delay 0.5
end repeat
say "OK"
or
tell application "TextEdit"
activate
end tell
repeat until (application "TextEdit" is running)
say "Beurk, I must wait"
delay 0.5
end repeat
say "OK"
You will never ear “Beurk, I must wait”
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) vendredi 13 septembre 2019 17:57:18
Your original code enter an infinite loop which I guess is not what you want.
An alternate way would be :
tell application "TextEdit"
set myDoc to make new document
end tell
display dialog "press OK when you are ready to quit" giving up after 60 * 2 # you have 2 minutes to work upon the doc
# If you press OK, the script wil execute the code available below
say "OK, you have finished with TextEdit"
With it you may work upon the document created during up to 2 minutes then the script will execute the trailing instructions.
I ran it, typed some text in the document, saved it and quitted TextEdit
Of course it’s just an example.
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) vendredi 13 septembre 2019 18:52:11
A less expensive alternative is to save the script as stay-open application and add the on idle handler
If the applet is not quit in the continueScript handler the idle handler is still called
on run
activate application "TextEdit"
end run
on idle
if application "TextEdit" is not running then continueScript()
return 2.0
end idle
on continueScript()
say "OK"
quit
end continueScript
StefanK. Thanks for the excellent suggestion. I compared it with my original script with the activity monitor open and your script does indeed use fewer resources. It’s nice to learn something new.
I tested 2 variants too.
Indeed, the on idle variant takes less CPU(%) and CPU time. In the CPU time the difference grows noticeably over time. So, this is a good example, indicating that, at least in AppleScript, it is better to use on idle instead of an infinite loop with exit by condition.
I was rewriting my full script using StefanK’s suggestion and, just to learn, read Bill Cheeseman’s post on stay-open Applescripts and idle handlers. It’s 13 years old but still very informative.
Anyways, I was interested to read the paragraph copied below. Bill is discussing scripts that are very complex, but the basic principle involved would seem to apply to my script.
“A common mistake is to overlook the idle handler and instead code a simple repeat loop that counts to a fixed number, testing for the desired condition at each iteration. The CPU then spends most of its time counting and testing, and the other processes will take much longer to complete–some, such as modem connections, may not work at all because of sensitive timing requirements. The speedup in other processes that is accomplished by using the idle handler to construct a wait loop can be astonishing.”