Jak Sprawdzić w AppleScript, czy aplikacja jest uruchomiona, bez jej uruchamiania-za pomocą narzędzia osascript

Rozważ następujący 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

Problem: gdy uruchamiam to za pomocą narzędzia linii poleceń osascript, Jeśli Safari nie jest uruchomione, zostanie uruchomione, a skrypt zgłosi "uruchomiony". Nie jest to zachowanie, którego pragnę lub oczekiwałbym. Zauważ, że działa zgodnie z oczekiwaniami, gdy jest uruchamiany w edytorze AppleScript.

Czy to jest osascript Błąd / znany problem? Czy jest to w jakiś sposób zamierzone zachowanie z powodów, których mi brakuje? Czy ktoś może go uruchomić zgodnie z życzeniem? (BTW jestem uruchamianie OSX 10.7.5; nie widzę jak zmusić osascript do zgłoszenia numeru wersji).

Jeśli skomentujesz tell / end tell lines, zachowuje się tak, jak bym się spodziewał: jeśli Safari nie działa, nie uruchamia go i wypisuje "nie działa". Więc to wydaje mi się, jakby tell było przyczyną uruchomienia Safari, ale nie musi być faktycznie wykonane, tylko obecne w skrypcie...? Przez jakiś czas zastanawiałem się, czy może tak właśnie powinno działać tell, ale skoro nie działa tak w edytorze AppleScript, chyba nie...

W rzeczywistości, oto inna, madder, wersja z podobnym zachowaniem:

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

To nadal uruchamia Safari, mimo że tell znajduje się wewnątrz if false bloku po instrukcji return! (Ale znowu, jest to w porządku w edytorze AppleScript.)

BTW, to zachowanie nie ogranicza się do Safari, ale też nie jest uniwersalne:

    [32]}dotknięte aplikacje to: Safari, TextEdit, iPhoto, AppleScript Redaktor, iTerm,..
  • aplikacje bez wpływu obejmują: Google Chrome, iTunes, podgląd, Poczta, Terminal, Książka Adresowa, Echofon,...

Więc, czy ktoś ma jakieś pomysły, Jak mogę naprawić lub trasy wokół tego? Czy to pluskwa? A może coś mi umyka w semantyce AppleScript?

Dla kontekstu: próbuję napisać skrypt (do osadzenia/wywołania z jakiegoś Pythona), który zapytuje otwarte przeglądarki o adresy URL wszystkich kart, które mają otwarte; mam to wszystko działa dobrze z wyjątkiem, że zawsze uruchamia Safari, niezależnie od tego, czy jest otwarte, czy nie. Skupiłem to niepożądane zachowanie na prostym przypadku testowym pokazanym powyżej. Nie znam żadnego sposobu uruchomienia tego skryptu z Pythona bez użycia osascript, innego niż appscript, którego nie chcę używać, ponieważ nie jest już rozwijany/obsługiwany/zalecany.

Wielkie dzięki za wszystkie wejścia / spostrzeżenia!

Author: gimboland, 2013-04-17

6 answers

Podejrzewam, że otrzymujesz to, ponieważ za każdym razem, gdy wywołujesz skrypt z linii poleceń za pomocą osascript, skrypt jest kompilowany.

Akt kompilacji natell aplikacji będzie afaik uruchomić aplikację.

Wywołanie skryptu z linii poleceń za pomocą osascript z wstępnie skompilowanego pliku tj.scpt nie powoduje takiego zachowania, ponieważ nie ma możliwości kompilacji.

Ale wywołanie go z pliku tekstowego (. txt,.sh ) czy więc aplikacja zostanie uruchomiona.

Jeśli nie chcesz używać a .plik scpt i chcesz użyć zwykłego pliku tekstowego, możesz wypróbować sztuczkę polegającą na umieszczeniu run script w applescripcie.

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

Skrypt w run script jest kompilowany tylko w razie potrzeby. Będziesz musiał uciec żadnych znaków, takich jak cytaty, jak w moim przykładzie.

Będzie łatwiej, jeśli najpierw napiszesz skrypt w normalnym dokumencie applescript i skompilujesz go, aby sprawdzić, czy błędy.

Następnie skopiuj go do zwykłego pliku tekstowego.


Aktualizacja **

Metoda, której użyłem powyżej, pochodziła ze starego skryptu, którego użyłem do rozwiązania tego problemu na chwilę przed tym, jak odpowiedziałem tutaj.

Odpowiedź działa i nie stara się być elegancka. ;-)

Naprawdę podoba mi sięuser1804762 metoda poniżej. Ponieważ to działa, ale czuję, że odpowiedź nie jest wystarczająco jasna, więc podam przykład korzystania z niego.

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

Skrypt ten można uruchomić z polecenia linia z osascript

Przykład:

osascript /Users/USERNAME/Desktop/foo.scpt

Zauważ, że skrypt jest zapisywany jako skompilowany skrypt. To będzie działać ok i można również zapisać i używać go jako zwykły skrypt tekstowy.

Tzn.

osascript /Users/USERNAME/Desktop/foo.applescript

 43
Author: markhunte,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-26 23:57:29

Niektóre Informacje:

"Rozszerzony Model Obiektowy Aplikacji":

tell application "iTunes"
    if it is running then
      pause
    end if
end tell

Możesz też to zrobić w ten sposób:

if application "iTunes" is running then
    tell application "iTunes" to quit
end if
Możesz też to zrobić:
get name of application "iTunes"
get version of application "iTunes"

I aby ukończyć podróż:

get id of application "TextEdit" --> "com.apple.TextEdit"
tell application id "com.apple.TextEdit"
    make new document
end tell

To był "ulepszony model obiektowy aplikacji". Jeśli aplikacja nadal uruchamia się (na przykład, po raz pierwszy skompilować & wykonać skrypt) zakładam, że to dlatego, że AS ma uzyskać pewne informacje z aplikacji, które nie znaleziono w słowniku (lub coś w tym stylu...?).

 45
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-17 20:48:47

OK, wiem, że to pytanie jest naprawdę stare, ale natknąłem się na nie szukając innego problemu i musiałem się spieszyć, biorąc pod uwagę, jak skomplikowane są niektóre z tych odpowiedzi.

Prosty kod do osiągnięcia tego,co chcesz (ed) to:

tell application "System Events"
  if application process "Safari" exists then
    -- do stuff you want to do only if Safari exists
  end if
end tell

W starszych systemach składnia używana to:

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

Jeden z nich powinien zdecydowanie działać dla Ciebie, nieustraszony poszukiwacz rozwiązań Applescript do działania tylko wtedy, gdy aplikacja jest uruchomiona.


Oh! Bonus wskazówka: a jeśli nie jesteś pewien, jaka jest dokładnie Nazwa procesu aplikacji (jest to Zwykle, ale nie zawsze Nazwa aplikacji), przed zakodowaniem ostatecznego skryptu Uruchom ...

tell application "System Events"
   get every application process
end tell

I znajdź nazwę procesu aplikacji w wynikach.

Oto screen z uruchomienia tej komendy. (Zwróć uwagę na zillions instancji Google Chrome Helper. Dzięki Google!)

Tutaj wpisz opis obrazka

HTH!
 7
Author: dashard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-23 07:17:12
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

This is return {"Finder", "JavaAppLauncher", "firefox", "Microsoft Word", "iTunes", "AppleScript Editor"} for me

Hope this helps

 1
Author: Kamin Pallaghy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-21 13:19:43

Wszystkie wcześniej wykonane odpowiedzi cierpią z tego samego problemu, choć:

Szukają aplikacji po jej nazwie. Jednak użytkownik może zmienić nazwę aplikacji, a następnie skrypt uwierzy, że aplikacja nie działa, podczas gdy w rzeczywistości tak.

Aby prawidłowo sprawdzić, czy uruchomiona aplikacja, powinna być znaleziona po identyfikatorze pakietu, którego Użytkownik nie może zmienić.

Identyfikator pakietu może być zapytany za pomocą tego polecenia, na przykład:

tell application "System Events"
    get bundle identifier of application process "Safari"
end tell

Aby sprawdzić, czy aplikacja z określonym pakietem ID działa, użyj tego kodu:

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

Ponadto, oto przykład, aby sprawdzić, czy aplikacja jest uruchomiona, a następnie zamknąć ją, a następnie uruchomić ponownie, upewniając się, że ta sama aplikacja jest ponownie uruchomiona przed, a nie jakaś inna kopia, która może również istnieć:

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
 1
Author: Thomas Tempelmann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-12 19:34:06

Miałem ten sam problem, jak opisano tutaj, próbując skonfigurować AppleScript (wyzwalany gestem BetterTouchTool), który odtwarza / zatrzymuje VLC lub iTunes, ale tylko iTunes, jeśli VLC nie jest uruchomiony (z powodu mojego przepływu pracy) i, oczywiście, tylko VLC, gdy jest uruchomiony. (Używam automatycznego wyzwalacza pauzy/odtwarzania dla iTunes w Ustawieniach VLC, do uruchamiania i zamykania aplikacji.)

VLC był zawsze uruchamiany przy pierwszym użyciu wyzwalacza BetterTouchTool po każdym ponownym uruchomieniu BTT, ponieważ dictionary-cache jest usunięte w tym momencie, a obsługa AppleScript musi uruchomić każdą aplikację skryptową, jeśli tell jest skierowany do niej, aby wywołać jej słownik.

Nigdzie nie znalazłem niczego, co mogłoby tego uniknąć; były pewne próby, ale żadna nie zadziałała dla mnie, ponieważ wywołanie słownika przez obsługę skryptu nie jest niczym, na co możemy mieć wpływ. Wymyśliłem to brudne obejście:

  • Utwórz oddzielny plik AppleScript zawierający tylko linię, która zawiera tell dla VLC
  • Save it w jakimś miejscu, gdzie nie będzie cię to denerwować
  • Zastąp linię zawierającą tell w oryginalnym Applescripcie linią uruchamiającą ten skrypt

Spowoduje to, że pierwsza Kompilacja skryptu nie wywoła aplikacji (VLC, w moim przypadku) bezpośrednio, tylko skrypt, co oznacza, że aplikacja nie będzie musiała się uruchamiać.

VLC będzie musiał uruchomić po wywołaniu oddzielnego pliku, ale cóż, jeśli wywołasz ten plik, aby powiedzieć coś VLC, czy VLC jest już otwarty (lub będzie chciał go otworzyć) tak czy inaczej.

AppleScript, który wywołuję przez mój BetterTouchTool-trigger (konkretne dotknięcie na gładziku, w moim przypadku) wygląda tak:

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

End if jeżeli aplikacja" VLC " jest uruchomiona to uruchom skrypt " / Users/jannis/bin / PlayVLC.scpt" end if

Oddzielny plik AppleScript ("PLayVLC.scpt, zapisany w folderze o nazwie "bin" w moim folderze użytkownika, który utworzyłem ręcznie wieki temu do takich celów) jest właśnie taki:

tell application "VLC" to play

Jeśli jeśli otworzysz ten skrypt ręcznie, To oczywiście uruchomi on również VLC. Ale mam nadzieję, że nie będzie to konieczne często,ani nigdy.

Właściwie nie mam pojęcia, czy stwarza to jakieś głębsze problemy, o których Nie wiem, ponieważ nie jestem pro koderem; jeśli tak, proszę mnie powiadomić. Mam nadzieję, że to komuś pomoże!

 0
Author: jatenk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-24 17:42:53