I'm trying to make a script (among other things) need to know if a certain application is running. For maximum robustness, I'd like to find it by its filepath. Or, failing that, find it by its name or bundle identifier, and check its filepath. Just to complicate things, I have the app pa开发者_如何学Goth in POSIX form
What I want to do is something like this (using TextEdit as an example here)
tell application "System Events"
item 1 of (processes whose application file is "/Applications/TextEdit.app")
end tell
But that doens't work...
I'm no AppleScript genius but I've found that I can at least find a running process from its bundle identifier, and then get its file as a useless "alias":
tell application "System Events"
application file of item 1 of (processes whose bundle identifier is "com.apple.TextEdit")
end tell
I get alias Macintosh HD:Applications:TextEdit.app:
application file
-alias to a POSIX path and compare them as strings. Nor can I translate the POSIX path I have into an alias, and then compare.
So, what do I do?
Update/solution
Hat-tips to Paul R and regulus6633 for giving useful hints!
I should probably have been a little more specific. As I write in some comments below, figuring out if an is running when you only have its path isn't all the script should do. The point is in fact to locate the process that matches the path, and then do some GUI scripting. I.e. I can't use a simple ps
because I need access to the GUI/AppleScript stuff (specifically the process' windows).
I could technically do a ps
to get the PID (as regulus6633 suggests below), but the AppleScript is already running in a shell spawned by a Ruby script running in another shell, and it just seemed messy.
Ended up doing this (which seems like a lot, but it was necessary in the context of what I was doing):
on getProcessByPOSIXPath(posixPath, bundleID)
-- This file-as-alias seems really complex, but it's an easy way to normalize the path endings (i.e. trailing slash/colon)
set pathFile to (POSIX file posixPath) as alias
set thePath to pathFile as text
tell application "System Events"
repeat with activeProcess in (processes whose bundle identifier is bundleID)
try
set appFile to application file of activeProcess
if (appFile as text) is equal to thePath then return activeProcess
end try
end repeat
return null
end tell
end getProcessByPOSIXPath
Note that the posixPath
argument must be the path to the application's bundle (e.g. "/Applications/TextEdit.app/" with or without trailing slash) and not the actual executable file inside the bundle.
The bundleIdentifier
argument isn't necessary, but it speeds everything up a lot by narrowing the list of processes. If you want this to work just using the path, you can do this
on getProcessByPOSIXPath(posixPath)
set pathFile to (POSIX file posixPath) as alias
set thePath to pathFile as text
tell application "System Events"
repeat with activeProcess in processes
try
set appFile to application file of activeProcess
if (appFile as text) is equal to thePath then return activeProcess
end try
end repeat
return null
end tell
end getProcessByPOSIXPath
We have lots of tools on the Mac and you can usually find a solution. In your case I agree that you cannot filter on the "application file". You can probably only filter on strings, numbers, or bools.
However we do have other tools such as the command line and we also have access to objective-c methods. Here's a command line method...
set applicationPosixPath to "/Applications/Utilities/AppleScript Editor.app"
try
do shell script "/bin/ps -ef | grep " & quoted form of applicationPosixPath & " | grep -v grep"
return "application is running"
on error
return "application is not running"
end try
I think all you need to do is this:
tell application "System Events"
set theAlias to application file of item 1 of (processes whose bundle identifier is "com.apple.TextEdit")
set thePath to (the POSIX path of theAlias)
end tell
It seems to work for me, anyway...
精彩评论