Can't get POSIX Path of given application in Applescript - macos

I've written some Applescript to create a list of paths of all
applications running in the dock:
set appsRunning to []
tell application "System Events"
repeat with p in every application process
if background only of p is false then
set appsRunning to appsRunning & POSIX path of (path to application p)
end if
end repeat
end tell
But when it runs I get
the error - "Can't make application into type constant" and it
highlights path to application p.
I don't understand why this happens because when I run
set q to POSIX path of (path to application "Finder") -- or any other application
I get no error whatsoever and I see
"/System/Library/CoreServices/Finder.app/" returned in the Results
field.
How can I get this to work?
P.S. For my purposes it is essential that I get the path - the
application name simply won't do. (This is because when I get the name
of the application process, some of my applications which are SSBs
made using Fluid return "FluidApp" as their
name instead of "Gmail" or "Tumblr" or whatever site it is that
I've made into an application. I need to distinguish between these and
that only happens when I get the path.)
Any help would be appreciated! Thanks.
Update: I used an amended version of the first suggestion in #vadian's answer to solve my problem:
set appsRunning to {}
tell application "System Events"
repeat with aProcess in (get application file of every application process whose background only is false)
set appsRunning to appsRunning & POSIX path of aProcess
end repeat
end tell

The element application process of System Events has a property application file, which you can get the POSIX path directly from.
set appsRunning to {}
tell application "System Events"
repeat with aProcess in (get every application process whose background only is false)
set end of appsRunning to POSIX path of application file of aProcess
end repeat
end tell
or easier
tell application "System Events"
set appsRunning to POSIX path of application file of every application process whose background only is false
end tell
additional here a solution which excludes the Finder because it runs all the time and the path is fixed
tell application "System Events"
set appsRunning to POSIX path of application file of every application process whose background only is false and name is not "Finder"
end tell
set end of appsRunning to "/System/Library/CoreServices/Finder.app"
another solution using your original approach
set appsRunning to {}
tell application "System Events"
set applicationNames to get name of every application process whose background only is false
end tell
repeat with aName in applicationNames
set end of appsRunning to POSIX path of (path to application aName)
end repeat
and last but not least the AppleScriptObjC version (Mavericks and higher, in Mavericks only in a script library)
set appsRunning to (current application's NSWorkspace's sharedWorkspace()'s launchedApplications()'s valueForKey:"NSApplicationPath") as list
Though the method launchedApplications of NSWorkspace is deprecated, it works in Yosemite
to use the AppleScriptObjC in a script library save this code
use framework "Foundation"
on launchedApplications()
return (current application's NSWorkspace's sharedWorkspace()'s launchedApplications()'s valueForKey:"NSApplicationPath") as list
end launchedApplications
as script bundle (in Mavericks you have to check "AppleScript/Objective-C library" in the side bar of the script) in ~/Library/Script Libraries. Create the folder if it doesn't exist.
Now you can call the script library from a normal script file (the script library is named "NSWorkspace.scptd")
use script "NSWorkspace"
set appsRunning to launchedApplications() of script "NSWorkspace"

Related

Is there an application type in applescript?

Is there an application type in AppleScript?
I have this handler:
on doHandler(theApplication)
set theApp to ("\"" & theApplication & "\"")
tell application theApp
set frontWindow to theApp's (window 1)
etc.
end tell
end doHandler
It is accessed as follows:
doHandler("TextEdit")
This produces the obvious error on theApp's (window 1).
So, what is the correct call?
This cannot work. The argument of tell application must be a literal string because the terminology is evaluated at compile time.
Apart from that the code doesn't work anyway because it expects that every application has an AppleScript dictionary containing a window property which is not the case.
All you need to do is eliminate the line set theApp to... and use the its keyword to set up the correct reference.
doHandler("TextEdit")
on doHandler(theApplication)
tell application theApplication
set frontWindow to its (window 1)
end tell
end doHandler
In the main script, application references are established at compile time, so you can't have a variable app name, but handlers aren't evaluated until run time.

Check if two files are the same in Applescript

I'm trying to get the bibliographic information of the currently open PDF in Skim.
To do that, I am comparing the file to the linked files of all the publications I have in BibDesk.
But for some reason, that comparison doesn't work:
tell application "Skim"
set theFile to the file of the front document
tell application "BibDesk"
repeat with currentPub in publications of front document
set bibFile to linked file of currentPub
if bibFile = theFile then
say "lala"
end if
end repeat
end tell
end tell
The script does get both theFile and bibFile correctly, but comparing them doesn't work. Why is that and what do I need to do differently?
Turns out it's super easy: you just have to compare with as string:
tell application "Skim"
set theFile to the file of the front document
tell application "BibDesk"
repeat with currentPub in publications of front document
set bibFile to linked file of currentPub
if bibFile as string = theFile as string then
say "lala"
end if
end repeat
end tell
end tell

Filling in gaps in itunes

I am new to appplescript and programming in general. would someone be so kind as to look over my code. I know its not in proper applescript syntax yet, as I struggled to find that information.
tell application iTunes
for each track in library playlist{ #all listed tracks, regardless of what files i have. may include dead links
set tr to track name
if file location is missing then search for it at external/Music/iTunes else messagebox(tr no file)
if search has result cut and paste to Music/itunes
check if file now exists else messagebox(tr error)
} end tell
I'll get you started. Here's how you can find the song name and artist of all tracks not found on your computer. You'll have to build on this to do the rest of your stuff.
set missingTracks to {}
tell application "iTunes"
set alltracks to tracks of library playlist 1
repeat with aTrack in alltracks
set theLocation to location of aTrack
set doesExist to my fileExists(theLocation)
if not doesExist then
set thisInfo to {songName:name of aTrack, songArtist:artist of aTrack}
set end of missingTracks to thisInfo
end if
end repeat
end tell
return missingTracks
on fileExists(theLocation)
tell application "Finder"
if exists theLocation then
return true
else
return false
end if
end tell
end fileExists

Check for part of a folder name in applescript

I have an applescript that checks for one of several external HDs I connect to my computer and makes an index of their contents. All the HDs follow the naming scheme HK_12345 where the first two letters are always the same but the numbers are different for each drive. I want the script to only check for drives with the 'HK' designation regardless of the ending numbers. I have this but it is not working. Any advice?
set folderContains to "HK_"
tell application "Finder"
set triggerFolder to folder whose name contains folderContains
end tell
tell application "Finder"
if folder triggerFolder exists then
-- some other code
end if
end tell
You should check for disks not folders:
set diskContains to "HK_"
tell application "Finder"
set selectedDisks to disks whose name contains diskContains
-- some other code
end tell

Check if an application exists using AppleScript

This code does not work for apps that do not exist because it prompts the user to look for "FooApp" (and I don't want to interact with the user):
get exists application "FooApp"
This code only works for apps whose process name matches its application name, which covers most but not all applications:
tell application "System Events"
get exists application process "FooApp"
end tell
(For example on my machine "OmniGraffle Professional" is a process name but the corresponding application name is "OmniGraffle Professional 4".)
#regulus6633 is right to point out you’re doing two separate things in your examples, and also his advice about bundle identifiers is spot on.
My preferred way to check if an application is installed is the following:
try
tell application "Finder" to get application file id "bundle.id.here"
set appExists to true
on error
set appExists to false
end try
This avoids the “Where is application x?” dialog and assigns a boolean value to appExists. You could also display alert in the on error block (or anything you desire).
For your second example, you could write:
tell application "System Events"
set processIsRunning to ((bundle identifier of processes) ¬
contains "com.bundle.id.here")
end tell
It does almost exactly what #regulus6633’s code does, but grabs the list of processes and checks it in a single line. You also don’t have to worry about initialising processIsRunning.
If you're using application names just swap bundle identifier for name.
Notice that your 2 scripts do different things. The first one checks if it is on the computer. The second one checks if it is currently running. So here's how to do the first thing.
set doesExist to false
try
do shell script "osascript -e 'exists application \"foo\"'"
set doesExist to true
end try
return doesExist
And note that as you point out some applications have a variety of names. In those cases you can use the bundle id of the app instead of it's name. Here's how to get the id of Safari and use it...
set appID to id of application "Safari"
exists application id appID
And if you wanted to see if it is running, like in your second script, you could do this...
set processIsRunning to true
tell application "System Events"
set runningProcesses to processes whose bundle identifier is appID
end tell
if runningProcesses is {} then set processIsRunning to false
return processIsRunning
This is an old question but the answer may still be helpful. The following shell script doesn't launch the application, avoids the "Where is application x?" dialog if the application doesn't exist, accepts either the application name or bundle id as input, and returns the application's bundle id if it exists or an empty string if it doesn't:
set appBundleId to do shell script "osascript -e " & ("id of application \"" & appRef & "\"")'s quoted form & " || osascript -e " & ("id of application id \"" & appRef & "\"")'s quoted form & " || :"
set doesExist to (appBundleId ≠ "")
where appRef is either the application name or bundle id.
Another way of doing this, should you have two applications with the same bundle identifier, is to use the application names. For instance, Adobe InDesign CS5.5 and Adobe InDesign CS6 both have com.adobe.InDesign as their bundle identifier.
tell application "System Events"
name of every process contains ("Adobe Photoshop CS5.5")
end tell

Resources