I’ve got a person having trouble with one of my scripts, and I’m having trouble explaining it. So I sent her a simple, one-line script to try:
tell application “System Events” to set appNameIsRunning to exists (processes where name is “Safari”)
When she runs that, it gives the following result:
error “System Events got an error: Application isn’t running.” number -600
She sent me a screenshot of the Events and Replies section in AppleScript Editor after running this script, and it showed:
tell application “AppleScript Editor”
exists every <> whose name = “Safari”
This repeats multiple times, then shows the above result.
Anybody know what’s going on here? This script has worked for many other people without issues.
it looks like the command is being sent to ASE rather than System Events, which is quit odd. You might get her to try:
tell application id "com.apple.systemevents" to set appNameIsRunning to exists (processes where name is "Safari")
I’m not so sure. Take this script:
tell application "System Events" to quit
tell application "System Events" to set appNameIsRunning to exists (processes where name is "Safari")
On my machine, running it in ASE with the Result pane showing and then switching to the Events/Replies pane does indeed show this:
The initial commands, sent to the non-running System Events, are shown as being sent to ASE. This could just be some quirk of ASE’s as it tries to render the event sequence retrospectively.
Running the script with the Events/Replies pane showing at the time produces this in the pane:
In both cases, there are two attempts at the ‘exists’ command, the first being shown with a class token instead of the ‘process’ keyword because ASE can’t get the keyword from the then non-running System Events.
The “standard practice” with faceless applications is to use an explicit ‘launch’ command:
tell application "System Events" to quit
tell application "System Events"
set appNameIsRunning to exists (processes where name is "Safari")
Here, the event listing only show one ‘exists’ attempt (usually):
I haven’t been able to reproduce treed’s “Application isn’t running” error, but System Events does autoquit after a certain amount of time, so it could be connected with that. There could be some problem relaunching it on the machine involved.
So, if I’m understanding correctly, System Events may not always be running, and if it isn’t, an AppleScript applet will repeatedly re-try sending the underlying Apple Event to System Events until either System Events finishes launching or it decides to time out. Is that right? That could certainly explain the screenshot I’m seeing from the affected individual, where the “tell” block seems to be executing seven times, according to the Events/Replies pane.
Is there anything I can do on my end to fix this? Should I be using ‘launch’ as the first command in every ‘tell application “System Events”’ block? Will that guarantee that System Events is loaded before proceeding, or is timing out still a possible problem? Of course, I wouldn’t want to eliminate the timeout altogether, so that the applet just froze on a system that was damaged in some way and couldn’t open System Events.
Interesting – I’m seeing it too, and without the switch. Whereas if I run with the id form, I get:
No sign of the quit.
You probably should the first time. You can also set the timeout:
tell application id "com.apple.systemevents" -- System Events.app
set quit delay to 1000
What I think is happening is this. When you run a script, AS resolves the target applications, but presumably it only does it the first time a particular app is targeted, re-using the value for all references. But normal AppleScript targets when you refer to an application by name are defined according to the application’s process number.
So when System Events quits, the process number is no longer valid, and the command therefore goes to the default target, which is ASE.
When you refer to apps by id, they are resolved differently, via launch services, so they don’t go “stale” if an app quits at some stage.
The moral of the story is that it’s probably a good idea to set a quit delay when scripting System Events and you’re likely to address it multiple times over a period of time. Apart from anything else, it will avoid delays. But it’s probably also a good idea to address System Events (or any app you intend to quit and relaunch within a script) by id rather than name.