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.
If I simplify the script to just displaying the notifications like (removing the tell aplication
block 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 and path is " & cd
else
display notification "not running and path is " & cdPath
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? Why will the "tell application" block open the app even if it's on the other branch of the conditional?
The use of "is running" is causing a run of the tell block. Use system events to get the name of running processes to check if the app is running. Here is a rewrite of your final script example that works as you wish.
on run {input, parameters}
set cdPath to "cd " & (quoted form of POSIX path of (input as string))
tell application "System Events" to set theProcesses to name of every process whose visible is true
if theProcesses contains "iTerm" then
display notification "running"
else
display notification "not running"
tell application "iTerm"
activate
end tell
end if
return input
end run
If you still can't get that to work (which does on my machine running OS X 10.11.1, then you can also add the trick where you wrap any tell block inside of a run script, so it never compiles until runtime. Here's your original script, demonstrating this:
on run {input, parameters}
set cdPath to "cd " & (quoted form of POSIX path of (input as string))
tell application "System Events" to set theProcesses to name of every process
if theProcesses contains "iTerm" then
display notification "running"
run script "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"
run script "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