Как проверить 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 не запущен, она запускается, а script сообщает "Запуск". Это не то поведение, которое я желаю или ожидаю. Обратите внимание, что он работает по желанию/ожиданию при запуске в редакторе AppleScript.
Является ли это ошибкой osascript
/известной проблемой? Или это как-то поведенческое поведение по причинам, которые мне не хватает? Может ли кто-нибудь заставить его работать по своему желанию? (BTW Я запускаю OSX 10.7.5, я не вижу, как получить osascript
, чтобы сообщить номер версии).
Если вы прокомментируете строки tell
/end tell
, это будет выглядеть так, как я ожидал: если Safari не запущен, он не запускает его и печатает "Не работает". Так что мне кажется, что tell
вызывает запуск Safari, но его фактически не нужно выполнять, просто присутствуя в script...? Некоторое время я задавался вопросом, возможно ли это, как должно работать 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, iTerm,...
- Не затрагиваемые приложения включают: Google Chrome, iTunes, Preview, Mail, Terminal, Address Book, Echofon,...
Итак, есть ли у кого-нибудь какие-либо идеи о том, как я могу это исправить или направить? Это ошибка osascript
? Или мне что-то не хватает в семантике AppleScript?
В контексте: я пытаюсь написать script (для встраивания/вызова из некоторого python), который запрашивает открытые браузеры для URL-адресов любых вкладок, которые они открыли; У меня все работает нормально, за исключением того, что он всегда запускает Safari, независимо от того, открыта она или нет. Я сварил это нежелательное поведение в простом тестовом примере, показанном выше. Я не знаю, как запустить этот script из python без использования osascript
, кроме appscript, который я не хочу использовать потому что больше не разрабатывается/не поддерживается/не рекомендуется.
Большое спасибо за все входы/идеи!
Ответы
Ответ 1
Я подозреваю причину, по которой вы получаете это, потому что каждый раз, когда вы вызываете script из командной строки с osascript, компиляция script.
Акт компиляции приложения tell приведет к запуску приложения afaik.
Вызов script из командной строки с помощью osascript из предварительно скомпилированного файла i.e. scpt не вызывает этого поведения, потому что компиляция не выполняется.
Но вызов его из файла обычного текста (.txt,.sh) приведет к запуску приложения.
Если вы не хотите использовать .scpt файл и хотите использовать простой текстовый файл, тогда вы можете попробовать трюк по размещению команды run script в 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
script в run script компилируется только при необходимости. Вам нужно будет избегать любых символов, таких как кавычки, как в моем примере.
Это будет проще, если вы сначала напишете script в нормальном документе applescript и скомпилируете его, чтобы проверить наличие ошибок.
Затем скопируйте его в текстовый файл.
ОБНОВЛЕНИЕ **
Метод, который я использовал выше, был из старого script, который я использовал для решения этой проблемы некоторое время, прежде чем я ответил здесь.
Ответ работает и не пытается быть элегантным.; -)
Мне действительно нравится метод 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
Этот script может быть запущен из командной строки с osascript
Пример:
osascript /Users/USERNAME/Desktop/foo.scpt
Обратите внимание, что script сохраняется как скомпилированный script. Это будет работать нормально, и вы также можете сохранить и использовать его как обычный текст script.
то есть.
osascript /Users/USERNAME/Desktop/foo.applescript
Ответ 2
Некоторая информация:
"Расширенная модель объекта приложения":
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
Это была "Расширенная объектная модель приложения". Если приложение все еще запускается (например, при первом компиляции и выполнении script), я предполагаю, что это потому, что AS должна получить некоторую информацию из приложения, которое она не нашла в словаре (или что-то в этом роде..?).
Ответ 3
Хорошо, я знаю, что этот вопрос действительно старый, но я наткнулся на него, ища другую проблему, и мне пришлось перебирать вопрос о том, насколько сложны некоторые из этих ответов.
Простой код для достижения того, что вы хотите (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 для действий только при запуске приложения.
О! Бонусный совет: И если вы не уверены, что именно имя процесса приложения (обычно это не всегда имя приложения), перед кодированием вашего последнего запуска script...
tell application "System Events"
get every application process
end tell
И найдите свое имя процесса приложения в результатах.
Здесь выполняется захват экрана для запуска этой команды. (Обратите внимание на дваллион экземпляров Google Chrome Helper. Спасибо Google!)
![enter image description here]()
НТН!
Ответ 4
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"}
для меня
Надеюсь, что это поможет
Ответ 5
Все ранее сделанные ответы страдают от одной и той же проблемы:
Они ищут приложение по его названию. Тем не менее, пользователь может переименовать приложение, а затем script полагает, что приложение не запускается, когда это действительно так.
Чтобы правильно проверить запущенное приложение, его нужно найти по его идентификатору пакета, который пользователь не может изменить.
Идентификатор пакета можно запросить с помощью этой команды, например:
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