Automator service script ALWAYS launches application, disregarding conditional

applescriptautomatoritermservices

I wrote a little service script to open an iTerm terminal window on an arbitrary folder on Finder.

I want it to check if iTerm is running, and if it is to open the terminal session in a new tab instead of on an existing one.

The script goes like this:

on run {input, parameters}

set cdPath to "cd " & (quoted form of POSIX path of (input as string))

if application "iTerm" is running then
    display notification "running"
    tell application "iTerm"
        set termWin to (current terminal)
        tell termWin
            launch session "Default"
            tell the last session
                write text cdPath
            end tell
        end tell
    end tell
else
    display notification "not running"
    tell application "iTerm"
        activate
        set termWin2 to (current terminal)
        tell termWin2
            tell the last session
                write text cdPath
            end tell
        end tell
    end tell
end if
return input
end run

Problem is that when I run the script as a service, it will always behave as if iTerm was already running (displaying the "running" notification), even if iTerm is closed and very clearly NOT running.

But if I paste the same script to the Script Editor (setting cdPath to a literal, like set cdPath to "cd /etc") and execute it directly it will work correctly, either opening a new iTerm instance or reusing an existing one and creating a new tab, and display the corresponding notifications.

What's going on here? Why running the script as a service would detect the application as running no matter what?

Update

If I simplify the script to just displaying the notifications like this:

on run {input, parameters}

set cdPath to "cd " & (quoted form of POSIX path of (input as string))

  if application "iTerm" is running then
    display notification "running"
  else
    display notification "not running"
  end if
  return input
end run

It'll behave as expected (displaying 'running' or 'not running' accordingly).

But if I add the "tell application" part, it will always go the through "running" branch, no matter what.

E.g.:

on run {input, parameters}

set cdPath to "cd " & (quoted form of POSIX path of (input as string))

  if application "iTerm" is running then
    display notification "running"
  else
    display notification "not running"
    tell application "iTerm"
        activate
    end tell
  end if
  return input
end run

Will always open iTerm (even if the tell application "iTerm" it's on the "not running" branch, but display the "running" notification, from the "is running" branch… The mere presence of a "tell application" will trigger opening the app then the Service is run.

Is there a way to circumvent this?

Thanks and regards.

Best Answer

El-Capitans security restrictions are NOT responsible for erroneous behaviour above. I tested the script some more and found that:

  • Any "is running"-phrase needs to have a short "delay" in front of it to reliably return a true answer ... but still won't do so if called as an app's service.
  • Furthermore I guess that Automator scripts are somehow "pre-processed" before being run as Services.
    All if-branches are evaluated (played through) and thereby activated "just in case".

In jweaks code at stackoverflow, iTerm is only affected directly in the 2nd clause ("tell ...").

tell application "System Events" to set theProcesses to name of every ¬
    every process whose visible is true

if theProcesses contains "iTerm" then display notification "running"
else [...]


Try this code in ScriptEditor, Automator and as Service in Safari:

display notification "" & running of application "TextEdit"
tell application "TextEdit" to activate
quit application "TextEdit"
display notification "" & running of application "TextEdit"

You will get different results from AppleScript/Automator (=> false + true) and Safari (true + true).
Especially AppleScript/Automator's true from the 2nd notification is quite telling.

... however, if you insert just a minute delay, say 0.01, after the "quit" line, running will be tested as "false" - if the script is run from within AppleScript/Automator.