How to check in AppleScript if an app is running, without launching it - via osascript utility

后端 未结 6 653
眼角桃花
眼角桃花 2020-11-30 20:11

Consider the following AppleScript:

on is_running(appName)
    tell application \"System Events\" to (name of processes) contains appName
end is_running

set         


        
相关标签:
6条回答
  • 2020-11-30 20:27

    I had the same problem as described here trying to set up an AppleScript (triggered by a BetterTouchTool gesture) that plays/pauses VLC or iTunes, but only iTunes if VLC is not running (due to my workflow) and, naturally, only VLC while it's running. (I use the automatic pause/play trigger for iTunes in VLC's settings, for launch and quit of the app.)

    VLC was always launched on the first use of the BetterTouchTool-trigger after every relaunch of BTT as the dictionary-cache is deleted at that point and the AppleScript handler has to launch every scripted application if a tell is aimed at it in order to call its dictionary.

    I didn't find anything that avoided this anywhere; there were some attempts, but none worked for me as the dictionary-call by the script handler is nothing we can influence. I came up with this dirty workaround:

    • Create a separate AppleScript file only containing the line that includes the tell for VLC
    • Save it at some place where it won't annoy you
    • Replace the line containing the tell in the original AppleScript with a line that runs that script

    This will lead to the first compilation of the script not calling the application (VLC, in my case) directly, only the script, which means that the application will not need to launch.

    VLC will need to launch once that separate file is called, but, well, if you call that file in order to tell VLC something, you will have VLC already opened (or will want it open) anyway.

    The AppleScript I call through my BetterTouchTool-trigger (a specific tap on the trackpad, in my case) looks like this:

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

    end if if application "VLC" is running then run script "/Users/jannis/bin/PlayVLC.scpt" end if

    The separate AppleScript file ("PLayVLC.scpt, saved in a folder called "bin" in my user folder which I created manually ages ago for such purposes) is just this:

    tell application "VLC" to play
    

    If you open that script manually, it will of course also launch VLC. But that hopefully won't be necessary often, or ever.

    I actually have no idea if this creates any deeper problems I don't know of as I'm not a pro coder; if so, please notify me. I hope this helps anyone!

    0 讨论(0)
  • 2020-11-30 20:28

    OK, I know this question is really old, but I stumbled on it looking for a different issue and had to pipe in considering how complicated some of these responses are.

    The simple code to achieve what you want(ed) is:

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

    On older systems, the syntax used to be:

    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
    

    One of these should definitely work for you, intrepid searcher of Applescript solutions for action only when an app is running.


    Oh! Bonus tip: And if you're not sure what the application process name is exactly (it is usually but not always the app name), before coding your final script run…

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

    And find your app process name in the results.

    Here's a screen grab of running that command. (Note the zillions of Google Chrome Helper instances. Thanks Google!)

    enter image description here

    HTH!

    0 讨论(0)
  • 2020-11-30 20:33

    I suspect the reason you are getting this is because each time you call the script from the command line with osascript the script is being compiled.

    The act of compiling on a tell application will afaik make the app launch.

    Calling the script from the command line with osascript from a pre-compiled file i.e .scpt does not cause this behaviour because the is no compiling to be done.

    But calling it from a plain text (.txt,.sh ) file will so the app will launch.

    If you do not want to use a .scpt file and want to use a plain text file then you could try the trick of putting a run script command in the 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
    

    The script in the run script is only compiled when needed. You will need to escape any characters like quotes as in my example.

    It will be easier if you write the script in a normal applescript document first and compiled it to check for errors.

    Then copy it to the plain text file.


    UPDATE **

    The method I used above was from a old script I had used to solved this issue a while before I answered here.

    The answer works and is not trying to be elegant. ;-)

    I actually like user1804762 method below. As it does work but feel the Answer is not clear enough so I will give an example on using it.

    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
    

    This script can be run from the command line with osascript

    example:

    osascript /Users/USERNAME/Desktop/foo.scpt

    Notice that the script is saved as a compiled script. This will work ok and you can also save and use it as a plain text script.

    i.e.

    osascript /Users/USERNAME/Desktop/foo.applescript

    0 讨论(0)
  • 2020-11-30 20:43
    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 returning {"Finder", "JavaAppLauncher", "firefox", "Microsoft Word", "iTunes", "AppleScript Editor"} for me

    Hope this helps

    0 讨论(0)
  • 2020-11-30 20:46

    Some Info:

    "Enhanced Application Object Model":

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

    You can also do it that way:

    if application "iTunes" is running then
        tell application "iTunes" to quit
    end if
    

    You can also do this:

    get name of application "iTunes"
    get version of application "iTunes"
    

    And to complete the journey:

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

    That was the "Enhanced Application Object Model". If an app still launches (for example, the first time you compile & execute the script) I assume it is because AS has to get some info from the app which it did not found in the dictionary (or something like that...?).

    0 讨论(0)
  • 2020-11-30 20:47

    All the previously made answers suffer from the same issue, though:

    They look for the app by its name. However, the user may rename the app, and then the script will believe the app does not run, when in fact it does.

    To properly check for a running app, it should be found by its bundle ID, which the user cannot change.

    The bundle ID can be inquired with this command, for instance, when the app is already running:

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

    Or like this for any installed app:

    get id of application "Safari"
    

    To check whether an app with a particular bundle ID is running, use this code:

    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
    

    Furthermore, here's an example to check if an app is running, then quit it, then relaunch it, ensuring that the very same app is relaunched that was running before, and not some other copy that may also exist:

    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
    
    0 讨论(0)
提交回复
热议问题