Подтвердить что ты не робот

Как проверить 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, который я не хочу использовать потому что больше не разрабатывается/не поддерживается/не рекомендуется.

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

4b9b3361

Ответ 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