How can i get a list of running applications in the same order they appear when doing ⌘ + ⇥ from within an applescript?
I.e. if I use TextEdit, then Preview, then iCal, the order is
iCal, Preview, TextEdit
This question which asked if there was an API that could produce this list provided this answer:
$ cd /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework
$ nm LaunchServices | grep __LSCopyApplicationArrayInFrontToBackOrder
But how can I access this list from within an applescript?
tell application "System Events" to get name of every process
It looks sorted by launch date to me, but I don't know if that's reliable or not.
As for using the answer from SO: you would have to create a small program (or OSAX) in (Objective)-C to access that routine, make the program scriptable, then call that program/OSAX from your script.
Not sure as how to order them But this lists applications that are not background only
tell application "System Events" to get the name of every process whose background only is false
Related
How can I bring an application to front by its path?
i.e. Assume /Applications/MyApp.app have already started; At a time I want to bring that MyApp.app window to front by passing its path to AppleScript: myApplScript.scpt /Applications/MyApp.app.
I tried by this script, but this did not worked for me:
on run argv
set apppath to (item 1 of argv) as string
tell application "System Events"
set frontmost of every process whose path is apppath to true
end tell
end run
Thanks!
Usually, all you need to do is to activate the application, which switches focus to it (even if the application is already running):
activate application "MyApp"
You can use this command directly with its path like this:
activate application "/Applications/MyApp.app"
or, in your specific case,
activate application apppath
although you shouldn't need to.
If that doesn't work, you can try System Events:
tell application "System Events" to set frontmost of process "MyApp" to true
or, using its path:
tell application "System Events" to set the frontmost of the first process ¬
whose POSIX path of application file is "/Applications/MyApp.app" to true
Have you tried checking for the open files for the process?
There are several ways of doing this (see: this article)
Normally the application binary will be an open file of the process.
Keep in mind that the binary executable may be contained in a package and you will need to look for it by doing a show package contents in finder and then appending the path to the executable in the package. In the package check under /Contents/MacOs/.
This might take a long time if you have many open processes and therefore not very practical to run often.
Also take into account that a single executable file can be running in more then one process instance.
A pity that the standard Activity Monitor is not scriptable with applescript which I just verified hoping for a more applescript friendly solution. You should still be able to achieve the same result via calling the shell command line.
Also often the process name is equal or similar to the filename but that depends on the application or process you're looking for.
I'm guessing you must have different versions of the same app installed that you need to check for the application by pathname?
Or if you don't need to figure out the path name dynamically you can simply look it up in advance using the Activity Monitor or on the command line. There you can identify the process name that corresponds to you your running application that was started from the specified path. Knowing the process name in advance then makes it easy and you can simply use
tell application "System Events" to get application process "Name of My Application"
--insert the actions you want to perform on your running app here
end tell
To solve any process uniqueness issues in case the same app is running more then once you can always result to the pid or unix process Id. Here's an article on how to get the pid in applescript of a running app
I'm working on a script for Photoshop and was using application id "com.adobe.photoshop" to identify when Photoshop is open. Unfortunately this ONLY seems to work for whatever the default version is. I have several machines this needs to go on and they might have 3 or they might have 5 versions.
I'd like it to work with whatever version is currently open.
The only way I can think to do that is to have an initial check of
if application "Photoshop CS6" is running
set Appname to "Photoshop CS6
ect... ect... ect...
for each version, but that's messy and if the version doesn't exist it generates a popup asking for where that is located.
Any ideas? =/
if you are sure that Photoshop is already launched at the time you are running your script, you can do the check by looking to all running processes as bellow :
tell application "System Events" to set PShop to name of every process where name contains "Photoshop"
set AppliName to item 1 of PShop
if Photoshop is not running at that time, I suggest you to have a script which looks to every files of folder Application whose name contains Photoshop.
I have an OS X app, let's call it TestOSX.app. This is its displayed name (taken from the Info.plist CFBundleName key as far as I can tell).
For a variety of reasons (it can be circumvented by copying the app to another place or by opening it from Terminal; it does not work if CFBundleExecutable is not the binary per-se but a script that sets up some stuff before launching the binary itself...), I cannot rely on OS X's built-in policy to block someone from starting a second instance of the app, nor can I use the LSMultipleInstancesProhibited key. But I do want to make sure that every second instance started by the same user is going to quit before being able to modify some resources. Different users should be able to run their own single instace of the app at the same time (this is why LSMultipleInstancesProhibited is no-go).
(I wanted to build a mechanism relying on flock(1) but it does not exist under OS X.)
So, the strategy is: when a user launches my app, first check whether an older version is already running; if there is, send this latest app instance (that the script has been executed "from") a request to quit, and bring the old instance to foreground.
I cannot use the name of the process per-se, as the app may use some embedded tools (like a proprietary updater) which will have a different name than the app itself. This is why something like this won't work:
tell application "System Events"
set listOfProcesses to (name of every process where background only is false)
end tell
, as the identified process may simply say updater (which is a part of the TestOSX bundle).
I have a snippet, probably parts of the "big thing", but it doesn't work as expected:
tell application "System Events"
set theProcess to first application process whose displayed name is "TestOSX"
set theOtherProcess to second application process whose displayed name is "TestOSX"
set frontmost of theOtherProcess to true
end tell
, this one always brings to front only the 1st app's process.
And I don't get it why it doesn't work as expected, as long as:
tell application "System events"
set listOfProcesses to (name of every process whose (dsiplayed name is "TestOSX"))
end tell
returns both instances. I guess somewhere the mapping between the process and the name is being lost.
[Edit]
Tried to modify the snippet above using:
tell application "System Events"
set theOtherProcess to id of second application process whose displayed name is "TestOSX"
set frontmost of theOtherProcess to true
end tell
, yet I get the error:
"Can't set frontmost of 680102 to true."
(This may be because I have a script that actually launches the binary, as said above?)
Okay, I came up with an ugly solution.
The bash script that is launched by double-clicking on the app icon is going to check how many instances of my app are running (with the aid of an AppleScript). If the answer is more than one, the bash script will end, thus my whole app terminating.
My launcher.command script:
#!/bin/bash
val=$(osascript ./instances_counter.scpt "TestOSX")
and the instances_counter.scpt, making use of the argument I passed:
on run argv
tell application "System Events"
set theProcessList to every application process whose displayed name is item 1 of argv
set noOfProcesses to count of theProcessList
end tell
return noOfProcesses
end run
That's it.
The example I can think of that is most relevant to me is to be able to close the last.fm app when I close iTunes. I quite often forget to close last.fm and I find it rather annoying. I'm sure there are other uses...
Yes you can.
Over on my Blog thecocoaquest I have two posts that cover this.
The first Post shows you a methods of doing this with a applescript and using a Launch Agent.
Applescript – Quit or Launch Application if another is or is not running
Here is one of the examples:
If I have one App running the second app will launch and will always be running while the first app is running.
Or when I quit the first App the second app will also quit
#!/usr/bin/osascript
#Copyright Mark Hunte 2012
#http://www.markosx.com/thecocoaquest/kill-one-application-if-another-is-not-running-applescript
set appMustBeRunning to "xcode"
set appToKill to "Snippets"
tell application "System Events"
set appMustBeRunningID to (unix id of processes whose name is appMustBeRunning)
set appToKillID to (unix id of processes whose name is appToKill)
end tell
if appMustBeRunningID is {} then
try
tell application "Snippets" to quit
end try
else if appToKillID is {} then
tell application "Snippets" to launch
end if
The Second post is a revision showing how to add more than one master & slave application
Applescript – Quit or Launch Application script.. ( Revised )
Also has an a script for if you just want to run the Applescript as an Application.
I want to make an AppleScript to automate the task of switching resolution on the MacBook Pro Retina.
Searching the internet for "applescript system preferences" I came across a page where some preferences are show. Being the scaled resolution thing new, it is not documented.
This brings to a bigger problem I have with AppleScript (mind that apart from copy-pasting something I never really programmed in it). Where is the documentation that tells me, for instance, tha the System Preferences object is actually called "System Preferences", that it has objects called "pane", that they have an id and that the expose id is "com.apple.preference.expose"?
It seems like there must be some sort of "secret" documentation for every program, and they must be huge, mapping all the object hierarchies and possible actions. In the end, AppleScript core is minimal and all you do is manipulate such programs. But where are they documented?
Ok this is how it works:
Where is the documentation that tells me, for instance, tha the System Preferences object is actually called "System Preferences"
The object is called "System Preferences" because that is the exact name of the application. What you're telling Applescript with this is I want to speak to the application named System Preferences (tell application "System Preferences" ...)
that it has objects called "pane"
Now it's the fun part. If you open your Library window (in Applescript Editor, Window > Library) you will see that there is a collection of scriptable applications available, the thing is that 'System Preferences' is not there. So let's find it: File > Open Dictionary > System Preferences. Now you got a window that both lets you drill down all available classes/commands/properties of the app and also a split window with relevant documentation (if you click on SSystem Preferences you'll see Cpane and by clicking on this you'll see Pid among others). The id of the pane for once more would be the name of the pane (lowercased and concatenated - I'm still looking into documentation for a strict definition on this). I hope that this will get you started.
S:Suite
C:Class
P:Property
(the 'C' inside a circle stands for Command)
You're exactly right. Each program does have its own documentation for applescript. It's called its applescript dictionary. You can see the dictionary of any application by any of the following...
1) in AppleScript Editor, under the File menu, choose "Open Dictionary...". You can select an application from there and it will show its dictionary.
2) drag/drop an application onto the AppleScript Editor's icon.
3) there's a list of frequently-used dictionaries for fast access. Under the Window menu in AppleScript Editor choose "Library". You can double-click an application in that list. You can also modify that list to contain dictionaries that you want in the list.
Good luck.
You can ask AppleScript to tell you the ids for each of the panes.
tell application "System Preferences" to get the id of every pane
This is particuarly handy as it will tell you the ids for any third-party preference panes you have installed. For instance, I was able to work out that the pane for my Microsoft Natural keyboard is called com.microsoft.microsoftkeyboard
I haven't really explored this much yet, but I would expect that similar syntax exists to identify the objects within any scriptable application.
I have another issue but you can have a look to my question as there is some hint in my script about your issue
HOW TO: display a check mark, disable a menu item, refresh a menubar
For instance:
tell application "System Preferences"
reveal anchor "displaysDisplayTab" of pane id "com.apple.preference.displays"
end tell
This code should directly put you in the resolution preferences of the system preference.
Then you can make a code to recuperate all the UI elements of the pane so that you now which action to trigger. Something like this should also work:
tell application "System Events"
tell application process "System Preferences"
set frontmost to true
delay 1
return every UI element of front window
return name of every UI element of front window
end tell
end tell
Hope it helps