Как проверить AppleScript, если приложение запущено, без его запуска - через утилиту osascript
рассмотрим следующий AppleScript:
on is_running(appName)
tell application "System Events" to (name of processes) contains appName
end is_running
set safRunning to is_running("Safari")
if safRunning then
tell application "Safari"
-- Stuff I only want executed if Safari is running goes here.
end tell
return "Running"
else
return "Not running"
end if
проблема: когда я запускаю это через osascript
утилита командной строки, Если Safari не работает, она запускается, и скрипт сообщает "работает". Такого поведения я не желаю и не ожидал бы. Обратите внимание, что он работает по желанию / ожидаемому при запуске в Редакторе AppleScript.
это osascript
ошибка / известная проблема? Или это как-то намеренное поведение по причинам, которые я упускаю? Может ли кто-нибудь заставить его работать как пожелаете? (Кстати, я запускаю OSX 10.7.5; я не вижу, как получить osascript
сообщить номер версии).
если закомментировать tell
/ end tell
lines, он ведет себя так, как я ожидал: если Safari не работает, он не запускает его и печатает "не работает". Так это кажется мне нравится tell
это то, что вызывает запуск Safari, но его не нужно фактически выполнять, просто присутствует в скрипте...? Какое-то время я задавался вопросом, может быть, это было просто как tell
должен работать, но так как это не работать так в Редакторе AppleScript, я думаю, нет...
на самом деле, вот еще одна, Марена, версия с аналогичным поведением:
on is_running(appName)
tell application "System Events" to (name of processes) contains appName
end is_running
set safRunning to is_running("Safari")
return safRunning
if false then
tell application "Safari"
end tell
end if
это по-прежнему всегда запускает Safari, хотя tell
находится внутри if false
блок после инструкции return! (Но опять же, это прекрасно в Редакторе AppleScript.)
кстати, это поведение не ограничивается Safari, но это также не универсальный:
- затронутые приложения включают в себя: Safari, TextEdit, iPhoto, AppleScript Editor, iTerm, ...
- non-affected apps включают в себя: Google Chrome, iTunes, предварительный просмотр, Почта, терминал, адресная книга, Echofon, ...
так, у кого-нибудь есть идеи о том, как я могу исправить или обойти это? Это osascript
ошибка? Или я что-то упускаю из семантики AppleScript?
для контекста: я пытаюсь написать скрипт (с embedded / called from some python), который запрашивает открытые браузеры для URL-адресов любых открытых вкладок; у меня все работает нормально кроме что он всегда запускает Safari, независимо от того, открыт он или нет. Я свел это нежелательное поведение к простому тестовому случаю, показанному выше. Я не знаю, как запустить этот скрипт с python без использования osascript
, кроме appscript, который я не хочу использовать, потому что это уже не разработан/поддерживается / рекомендуется.
большое спасибо за все вводы / выводы!
6 ответов
Я подозреваю, что причина, по которой вы получаете это, заключается в том, что каждый раз, когда вы вызываете скрипт из командной строки с osascript, скрипт компилируется.
акт компиляции на рассказать приложением будет afaik сделать запуск приложения.
вызов скрипта из командной строки с помощью osascript из предварительно скомпилированного файла i.e .scpt не вызывает такого поведения, потому что компиляция не выполняется.
но вызов его из простой текст (.txt,.sh) файл будет так приложение будет запускаться.
если вы не хотите использовать .scpt-файл и хотите использовать текстовый файл, тогда вы можете попробовать трюк свыполнить скрипт команда в applescript.
on is_running(appName)
tell application "System Events" to (name of processes) contains appName
end is_running
set safRunning to is_running("Safari")
if safRunning then
run script "tell application \"Safari\"
open location \"http://google.com\"
end tell"
return "Running"
else
return "Not running"
end if
скрипт в выполнить скрипт компилируется только при необходимости. Вам нужно будет избежать любых символов, таких как цитаты, как в моем примере.
будет проще, если вы напишете скрипт в обычном режиме сначала документ applescript и скомпилировал его для проверки на наличие ошибок.
скопируйте его в текстовый файл.
обновление**
метод, который я использовал выше, был из старого сценария, который я использовал для решения этой проблемы некоторое время, прежде чем я ответил Здесь.
ответ работает и не пытается быть элегантным. ;-)
мне на самом деле нравится user1804762 способ ниже. Как это работает, но чувствую, что ответ не ясен достаточно, чтобы я привел пример его использования.
set appName to "Safari"
if application appName is running then
tell application id (id of application appName)
open location "http://google.com"
end tell
return "Running"
else
return "Not running"
end if
этот скрипт можно запустить из командной строки с помощью osascript
пример:
osascript /Users/USERNAME/Desktop/foo.scpt
обратите внимание, что скрипт сохраняется как скомпилированный скрипт. Это будет работать нормально, и вы также можете сохранить и использовать его как обычный текст сценария.
то есть
osascript /Users/USERNAME/Desktop/foo.applescript
Информация:
"Расширенная Объектная Модель Приложения":
tell application "iTunes"
if it is running then
pause
end if
end tell
вы также можете сделать это таким образом:
if application "iTunes" is running then
tell application "iTunes" to quit
end if
вы также можете сделать это:
get name of application "iTunes"
get version of application "iTunes"
и завершить путешествие:
get id of application "TextEdit" --> "com.apple.TextEdit"
tell application id "com.apple.TextEdit"
make new document
end tell
Это была "расширенная объектная модель приложения". Если приложение все еще запускается (например, при первом компиляции и выполнении скрипта), я предполагаю, что это связано с тем, что AS должен получить некоторую информацию из приложения, которое он не нашел в словарь (или что-то в этом роде...?).
хорошо, я знаю, что этот вопрос действительно старый, но я наткнулся на него, ища другую проблему, и мне пришлось трубить, учитывая, насколько сложны некоторые из этих ответов.
простой код для достижения того, что вы хотите (ed):
tell application "System Events"
if application process "Safari" exists then
-- do stuff you want to do only if Safari exists
end if
end tell
в старых системах синтаксис использовать для:
tell application "System Events"
if exists of application process "Safari" is true then
-- do stuff you want to do only if Safari exists
end if
end tell
один из них должен определенно работать для вас, бесстрашный искатель решений Applescript для действий только тогда, когда приложение бегущий.
о! бонус совет: и если вы не уверены, что имя процесса приложения ровно (это обычно а не всегда имя приложения), прежде чем кодировать ваш окончательный скрипт...
tell application "System Events"
get every application process
end tell
и найти имя процесса приложения в результатах.
вот захват экрана запуска этой команды. (Примечание миллиардами Google Chrome Helper экземпляров. Спасибо Гугл!)
HTH!
tell application "Finder"
set applicationsnames to get the name of every process whose visible is true
end tell
set appName to "Safari"
if applicationsnames does not contain appName then
say (appName & " is not running")
--add here what you want to happen
end if
return applicationsnames
Это возвращение {"Finder", "JavaAppLauncher", "firefox", "Microsoft Word", "iTunes", "AppleScript Editor"}
для меня
надеюсь, что это помогает
все ранее сделанные ответы страдают от той же проблемы, хотя:
они ищут приложение по его имени. Однако пользователь может переименовать приложение, и тогда скрипт поверит, что приложение не запускается, хотя на самом деле это так.
чтобы правильно проверить запущенное приложение, его следует найти по идентификатору пакета, который пользователь не может изменить.
идентификатор пакета можно запросить с помощью этой команды, например:
tell application "System Events"
get bundle identifier of application process "Safari"
end tell
чтобы проверить если приложение с определенным идентификатором пакета запущено, используйте этот код:
tell application "System Events"
set ids to bundle identifier of every application process
if ids contains "com.apple.safari" then
return "Running"
else
return "Not running"
end if
end tell
кроме того, вот пример, чтобы проверить, работает ли приложение, затем выйти из него, а затем перезапустить его, гарантируя, что то же самое приложение перезапущено, что и раньше, а не какая-то другая копия, которая также может существовать:
set bundleID to "com.apple.safari"
set apps to runningApps(bundleID)
set appCount to length of apps
if appCount is not 0 then
quit application id bundleID
repeat while length of runningApps(bundleID) = appCount
-- wait for the app to quit
end repeat
open first item of apps
end if
on runningApps(bundleID)
-- The try block is to catch the rare case of having more than one
-- copy of an app running at the same time. Unfortunately, in that
-- case this code will not run as expected, because we don't get the
-- correct list of multiple items back then. But at least the script
-- will not crash from it but handle it gracefully.
tell application "System Events"
try
return application file of (every application process whose bundle identifier = bundleID)
end try
end tell
return {}
end runningApps
у меня была такая же проблема, как описано здесь, пытаясь настроить AppleScript (вызванный жестом BetterTouchTool), который воспроизводит/приостанавливает VLC или iTunes, но только iTunes, Если VLC не работает (из-за моего рабочего процесса) и, естественно, только VLC во время его работы. (Я использую автоматический триггер паузы/воспроизведения для iTunes в настройках VLC для запуска и выхода из приложения.)
VLC всегда запускался при первом использовании bettertouchtool-trigger после каждого перезапуска BTT в качестве словарь-кэш удаляется в этот момент, и обработчик AppleScript должен запустить каждое скриптовое приложение, если tell нацелен на него, чтобы вызвать его словарь.
Я не нашел ничего, что избегало этого нигде; были некоторые попытки, но никто не работал для меня, так как вызов словаря обработчиком сценария-это ничто, на что мы можем повлиять. Я придумал этот грязный обходной путь:
- создайте отдельный файл AppleScript, содержащий только строку, которая включает скажите для VLC
- сохраните его в каком-нибудь месте, где он не будет раздражать вас
- замените строку, содержащую tell в исходном AppleScript, строкой, которая запускает этот скрипт
это приведет к первой компиляции скрипта, не вызывающего приложение (VLC, в моем случае) напрямую, только скрипт, что означает, что приложение не нужно будет запускать.
VLC нужно будет запустить после вызова этого отдельного файла, но, хорошо, если вы вызываете этот файл, чтобы сказать VLC что-то, у вас будет VLC уже открыт (или вы захотите его открыть) в любом случае.
AppleScript, который я вызываю через мой BetterTouchTool-trigger (конкретный кран на трекпаде, в моем случае), выглядит так:
if application "iTunes" is running and not application "VLC" is running then
tell application "iTunes" to playpause
конец если если приложение " VLC " работает, то run script " / пользователи / jannis/bin / PlayVLC.scpt" конец если
отдельный файл AppleScript ("PLayVLC.scpt, сохраненный в папке под названием "bin" в моей папке пользователя, которую я созданный вручную веками назад для таких целей) - это просто:
tell application "VLC" to play
Если вы откроете этот скрипт вручную, он, конечно, также запустит VLC. Но, надеюсь, это не будет необходимо часто или когда-либо.
Я на самом деле понятия не имею, создает ли это какие-либо более глубокие проблемы, о которых я не знаю, поскольку я не профессиональный кодер; если да, пожалуйста, сообщите мне. Надеюсь, это кому-то поможет!