Как проверить 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 командной строки osascript , если Safari не запущен, она запускается, а сценарий сообщает «Запуск». Это не то поведение, которое я желаю или ожидаю. Обратите внимание, что он работает по желанию / ожидаемому при запуске в редакторе AppleScript.

Это ошибка osascript / известная проблема? Или это как-то поведенческое поведение по причинам, которые мне не хватает? Может ли кто-нибудь заставить его работать по своему желанию? (BTW Я запускаю OSX 10.7.5, я не вижу, как получить osascript чтобы сообщить номер версии).

Если вы закомментируете строки tell / end tell , это будет выглядеть так, как я ожидал: если Safari не запущен, он не запускает его и печатает «Не работает». Так что мне кажется , что tell , что вызывает запуск Safari, но его не нужно фактически исполнять, просто присутствовать в скрипте …? Некоторое время я задавался вопросом, возможно ли это, как должно работать, но поскольку это не работает в AppleScript Editor, я не думаю …

На самом деле, вот еще одна, безумная версия с аналогичным поведением:

 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, даже если сообщение находится внутри блока if false после оператора return! (Но опять же, это хорошо в редакторе AppleScript.)

Кстати, это поведение не ограничивается Safari, но оно также не универсально:

  • К уязвимым приложениям относятся: Safari, TextEdit, iPhoto, редактор AppleScript, iTerm, …
  • Не затрагиваемые приложения include: Google Chrome, iTunes, Preview, Mail, Terminal, Address Book, Echofon, …

Итак, есть ли у кого-нибудь идеи о том, как я могу это исправить или направить? Это ошибка osascript ? Или мне что-то не хватает в семантике AppleScript?

Для контекста: я пытаюсь написать сценарий (который должен быть встроен / вызван с некоторого python), который запрашивает открытые браузеры для URL-адресов любых вкладок, которые они открыли; У меня все работает нормально, за исключением того, что он всегда запускает Safari, независимо от того, открыт он или нет. Я сварил это нежелательное поведение в простом тестовом примере, показанном выше. Я не знаю, как запускать этот скрипт из python, не используя osascript , кроме appscript , который я не хочу использовать, потому что он больше не разработан / не поддерживается / не рекомендуется .

Большое спасибо за все материалы / идеи!

Я подозреваю причину, по которой вы получаете это, потому что каждый раз, когда вы вызываете скрипт из командной строки с помощью osascript, скрипт компилируется.

Акт компиляции приложения-приложения сделает afaik запустит приложение.

Вызов сценария из командной строки с помощью osascript из предварительно скомпилированного файла, т.е. 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 . Спасибо Google!)

введите описание изображения здесь

НТН!

 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 после каждого повторного запуска BTT, когда кэш-словарь был удален в этот момент, и обработчик AppleScript должен запускать каждое приложение, написанное по сценарию, если на него наложено указание, чтобы вызвать его Словарь.

Я не нашел ничего, что бы никого не избегало; были некоторые попытки, но никто не работал для меня, так как словарь-вызов обработчиком скрипта ничто не может повлиять. Я придумал этот грязный обход:

  • Создайте отдельный файл AppleScript, содержащий только строку, которая включает в себя указание для VLC
  • Сохраните его в каком-то месте, где это вас не раздражает
  • Замените строку, содержащую подсказку в исходном AppleScript, строкой, которая запускает этот скрипт

Это приведет к первой компиляции скрипта, не вызывающего приложение (VLC, в моем случае) напрямую, только сценарий, что означает, что приложение не нужно запускать.

VLC нужно будет запустить, как только вызывается отдельный файл, но, если вы вызываете этот файл, чтобы что-то сказать VLC, вы все равно будете открывать VLC (или захотеть его открыть).

AppleScript я вызываю свой триггер BetterTouchTool (конкретный щелчок на трекпаде, в моем случае) выглядит следующим образом:

 if application "iTunes" is running and not application "VLC" is running then tell application "iTunes" to playpause 

если, если приложение «VLC» запущено, запустите сценарий «/Users/jannis/bin/PlayVLC.scpt», если

Отдельный файл AppleScript («PLayVLC.scpt», сохраненный в папке с именем «bin» в моей папке пользователя, которую я создал вручную в течение нескольких веков для таких целей):

 tell application "VLC" to play 

Если вы откроете этот скрипт вручную, он, конечно же, также запустит VLC. Но это, надеюсь, не понадобится часто или никогда.

На самом деле я понятия не имею, создает ли это какие-то более глубокие проблемы, о которых я не знаю, поскольку я не являюсь прокодером; Если это так, пожалуйста, сообщите мне. Надеюсь, это поможет кому угодно!

  • Похоже, что Firefox и Safari на Mac не могут показать веб-страницу в полноэкранном режиме?
  • Вызов jQuery .load () не выполняет JavaScript в загруженном HTML-файле
  • Как перенести содержимое моего портативного Firefox в установленный Firefox на моем ноутбуке?
  • Создание файла из blob
  • Safari продолжает запрашивать разрешение на доступ к цепочке ключей
  • Safari / Chrome (Webkit) - Не удается скрыть вертикальную полосу прокрутки iframe
  • Ошибка Webkit с `: hover` и несколькими соседними селекторами
  • iOS 7 iPad Safari Пейзаж innerHeight / внешний дизайн макета
  • Есть ли какие-либо расширения или трюки, чтобы открыть несколько закрытых вкладок в Safari
  • Выбор текста в фокусе с использованием jQuery, не работающего в Safari и Chrome
  • Программно воспроизводить видео со звуком в Safari и Mobile Chrome
  • Давайте будем гением компьютера.