Я написал небольшой служебный скрипт, чтобы открыть окно терминала iTerm в произвольной папке в Finder.
Я хочу, чтобы он проверял, запущен ли iTerm, и должен ли он открывать сеанс терминала на новой вкладке, а не на существующей.
Сценарий выглядит следующим образом:
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
Проблема в том, что когда я запускаю скрипт как службу, он всегда будет вести себя так, как будто iTerm уже запущен (отображая «работающее» уведомление), даже если iTerm закрыт и явно НЕ работает.
Но если я вставлю тот же скрипт в редактор скриптов (установив для cdPath литерал, например set cdPath to "cd /etc"
) и выполню его напрямую, он будет работать правильно, либо открыв новый экземпляр iTerm, либо повторно используя существующий и создав новую вкладку, и отобразив соответствующий уведомления.
Что тут происходит? Почему запуск скрипта как службы будет определять приложение как работающее, несмотря ни на что?
Обновлять
Если я упрощу скрипт, чтобы просто отображать уведомления следующим образом:
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
Он будет вести себя так, как ожидалось (отображение «работает» или «не работает» соответственно).
Но если я добавлю часть «сказать приложение», она всегда будет проходить через «работающую» ветвь, несмотря ни на что.
Например:
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
Всегда будет открывать iTerm (даже если tell application "iTerm"
он находится в «не работающей» ветке, но отображает «работающее» уведомление из ветки «работает»... Простое присутствие «сообщения о приложении» вызовет открытие приложения, а затем Служба запущена.
Есть ли способ обойти это?
Спасибо и привет.
Ограничения безопасности El-Capitans НЕ несут ответственности за ошибочное поведение, описанное выше. Я еще раз протестировал скрипт и обнаружил, что:
В коде jweaks при переполнении стека iTerm затрагивается только непосредственно во втором предложении («рассказать...»).
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 [...]
Попробуйте этот код в ScriptEditor, Automator и как сервис в Safari:
display notification "" & running of application "TextEdit"
tell application "TextEdit" to activate
quit application "TextEdit"
display notification "" & running of application "TextEdit"
Вы получите разные результаты от AppleScript/Automator (=> false + true ) и Safari ( true + true ). Особенно показательна правда
AppleScript/Automator из 2-го уведомления. ... однако, если вы вставите задержку всего в минуту, скажем, 0,01, после строки «выход», запуск будет проверен как «ложный» - если скрипт запускается из AppleScript/Automator.
Иногда я также замечал такое поведение при запуске скрипта, это странно. Хотя в большинстве случаев этого не происходит, если скрипт не запущен через редактор скриптов. Тем не менее, вот лучшая альтернатива:
tell application "System Events"
# Adding tell application block has no effect on the if condition
# Try it with TextEdit, that's what I using to try this code, and works fine.
if (the name of application processes as text) contains "iTerm" then
# Will quit the application if running
log "Running"
tell application "iTerm" to quit
else
# Will launch the application otherwise.
log "Not Running"
tell application "iTerm" to activate
end if
end tell
Я просто нашел способ сделать это. Хотя я создаю приложение вместо службы, они почти одинаковы. Основная идея состоит в том, чтобы поместить его tell application iTerm
в другой скрипт или в кавычки, чтобы процесс оптимизации не заставлял его открывать iTerm перед выполнением этого скрипта. Таким образом, вы получите реальный результат if application "iTerm" is running
.
Но в процитированном скрипте, поскольку есть tell application
часть, мы уже знаем, что iTerm будет открыт раньше всего, мы можем напрямую использовать activate
iTerm и использовать его current session of current terminal
(на самом деле, даже в Automator это все еще работает, даже если iTerm не открывается сначала). Я не уверен, что delay 0.01
здесь это необходимо (вы можете проверить на своем компьютере). Но это работает для моей цели, которая заключается в том, чтобы открыть текущий путь Finder в новом окне iTerm на текущем рабочем столе. И если iTerm не запущен, он не откроет два окна iTerm.
Дайте мне знать, что вы думаете. :-)
on run {input, parameters}
tell application "Finder"
set dir_path to quoted form of (POSIX path of (folder of the front window as alias))
end tell
CD_to(dir_path)
end run
on CD_to(theDir)
if application "iTerm" is running then
#display dialog "Running" # for debug
run script "
on run {q}
tell application \":Applications:iTerm.app\"
set term to (make new terminal) # make a new window in current desktop since I don't want to mess with current ones
tell term
launch session \"Default\"
set sesh to current session
end tell
tell sesh
write text \"cd \" & q & \";clear;\"
end tell
activate
end tell
end run
" with parameters {theDir}
else
#display dialog "Not Running" # for debug
run script "
on run {q}
tell application \":Applications:iTerm.app\"
delay 0.01
activate
set sesh to current session of current terminal
tell sesh
write text \"cd \" & q & \";clear;\"
end tell
end tell
end run
" with parameters {theDir}
end if
end CD_to
# part of code comes from http://peterdowns.com/posts/open-iterm-finder-service.html
астробойлркс