Applescript Tell Application launched by specific user - applescript

I am running two Skype on the same computer: one is launched normally and the other one is launched in Terminal under a different user account B.
Then, I want to use Applescript to Tell application "Skype" (which is launched by account B) to do something. How should I specific the instance of Skype that is launched by account B in Applescript?
Many thanks!
miu

Apparently this can be done without duplicating/renaming the app if you enable remote apple events on your mac. (This is a system preference under sharing, and requires admin clearance, although you can restrict which users are allowed to send apple events, which I would recommend for security reasons).
Once that is done, you should be able to do something like:
tell application "Skype" of machine "eppc://userB#127.0.0.1"
-- whatever
end tell
userB is of course the user name of user B, and 127.0.0.1 means 'this machine' or more correctly 'local host'.

I don't think you can. However I have thought of a work-around. Here's the idea. You can target an application several ways, one of them by its bundle identifier. For example to target TextEdit you could do this...
tell application id "com.apple.TextEdit" to activate
With that in mind, your 2 running versions of skype would need to have different bundle ids so you can target them separately. That's not the case right now but you can make that happen. Just duplicate the skype application (make a copy). Then open the package contents of the copy, open the "info.plist" file in there, find the bundle identifier key, and change it to something else. Now you have 2 versions of skype with different bundle ids which means you can target them separately.
I checked this using TextEdit. I made a duplicate copy and set its bundle id to "com.apple.myTextEdit". I opened both applications and could target them separately. So user B could use "com.apple.myTextEdit" and the normal user would use "com.apple.TextEdit"... or vice versa.
It's not an ideal solution but it would work.

I turned out to solve it by creating two copies of Skype.app and rename the new one "Skype2.app". Skpye.app is launched by user A and Skype2.app by user B (via Terminal). Then, in Applescript
tell application "Skype"
-- do something for user A
end tell
tell application "Skype2"
-- do something else for user B
end tell

Related

AppleScript: open frontmost file with another application

I'd like to write an AppleScript program to do the following (Automator would be fine too):
I want to open the current active TextMate file (possibly there are several tabs open and other windows) with the application Transmit 2. (This will upload the file over FTP using Transmit's DockSend feature.)
Here I've used a specific application (TextMate) but ideally I'd like it to work for any file currently active in any application.
Ultimately I will assign a keyboard shortcut to run it.
Here's what I have so far:
tell application (path to frontmost application as text)
set p to path of document 1
end tell
tell application "Finder"
open POSIX file p using "Transmit 2"
end tell
I've tried many variants of this and nothing works.
EDIT:
I have found this page: http://wiki.macromates.com/Main/Howtos and someone has made exactly the script I'm looking for:
tell application "Transmit" to open POSIX file "$TM_FILEPATH"
This is for Transmit [not 2] and I think for TextMate pre v2. I get the error (when using Transmit 2):
Transmit 2 got an error: AppleEvent handler failed.
One of the updates to v2 has broken it (not sure which one).
There appear to be two steps to your problem. One, get the path to the document (or some other reference that allows you to later open the document), and, two, open the document in the desired application.
If the AppleScript is saved as an application, the frontmost application is the AppleScript you’re running, and so that path will be the path to the AppleScript application. In that case, I’m not aware of how to get the second-frontmost application.
However, if the application supports the scripts folder (go into AppleScript Editor‘s preferences, and enable “Show Script menu in menu bar”), you can save the script as a “Script“ in the User Scripts folder, and when run from the scripts menu the frontmost application will be the application you’re currently in.
You may want to display the p variable when testing to ensure that you are getting the correct path and not the path to the AppleScript.
As far as opening the document in another application (such as Transmit), the best way to do this is to talk to the application directly if it supports it:
tell application (path to frontmost application as text)
set p to path of document 1
end tell
--for testing: verify that the path is for the correct document
display dialog p
tell application "Transmit 2"
open p
end tell
I don’t have Transmit, but I’ve verified that this works if I replace “Transmit 2” with Textastic or Smultron 6.
If you do need to use the Finder to open the document, the Finder seems to prefer its paths as strings, and also seems to prefer a full path to the application. Something like this should work:
tell application (path to frontmost application as text)
set p to path of document 1
end tell
--for testing: verify that the path is for the correct document
--display dialog p
set transmitPath to path to application "Transmit 2"
set p to POSIX file p as string
tell application "Finder"
open file p using transmitPath
end tell
Again, I’ve tested this using Textastic and Smultron as the applications.
The most common solution for the problem you are trying to solve is to run an app that makes your Web server appear to be a mounted Mac disk. Transmit 4 has that feature, which Panic calls “Transmit Disk.” But there are a few other apps also — Transmit was not the first.
Your Mac apps (and AppleScripts) just see a typical Mac disk that they can save files to and read files from (the most basic of basic AppleScript tasks) and yet Transmit Disk (or similar app) is transparently mirroring any changes to that Mac disk to your Web server in the background. This makes all the network and FTP stuff totally go away and leaves you writing very simple scripts that do very powerful things to your Web server. You Save HTML documents on there, you Export image and movie files onto there as easily as you would Save them on your Desktop, and yet they are immediately published to your Web server. Even the only barely scriptable apps can Save their files onto a particular disk.
For example, if I have an HTML document open in BBEdit and I want to save a copy of that document to my Web server, it only takes a few lines of code, which would likely be similar in any AppleScript-able text editor (this script would also work verbatim in the free TextWrangler):
tell application "BBEdit"
set theHTMLSource to the contents of text window 1
make new document with properties {text:theHTMLSource}
save document 1 to file "Transmit Disk:index.html"
close document 1 saving no
end tell
Notice that the AppleScript above not only doesn’t have to know anything about SFTP or have any login credentials, it doesn’t even have to figure out the file path of my current document because it just takes the content right out of the current window. There are no POSIX pathnames, no shell scripts, no monkey business at all. And because this task and code is so simple, you could conceivably rewrite this script 20 times for 20 different apps that you may use, so that they can all Save a copy of their current document onto your Transmit Disk, and thus publish that document to your Web server.
And if I have a folder of images that goes along with that HTML document, I can ask Finder to duplicate that folder onto my Transmit Disk to publish it. With just one line of code:
tell application "Finder"
duplicate folder "images" of (the path to the desktop folder as alias) to the disk "Transmit Disk" replacing no
end tell
… but those images could also be exported out of Photoshop or any app, right onto the Transmit Disk, via AppleScript.
In short, the thing that all of your Mac apps have in common is they can all Save files to a Mac disk. They can’t necessarily all give you the pathnames to the documents they have open, or open those files with Transmit. And Mac apps and AppleScript were designed primarily to work with files Saved or Opened to/from local disks. So you gain a lot if you use something like Transmit Disk to make your Web server basically part of the AppleScript party, by making it appear to be just a plain old Mac disk.

Display dialog to a remote machine via EPPC

How can I send a display dialog to a remote machine via EPPC? I believe Scripting Addition Security in the release notes discusses the issue but I have not been able to resolve it yet. Release Notes
Attempt 1
using terms from application "Finder"
set remoteFinder to application "Finder" of machine "eppc://user:password#host"
tell remoteFinder to display dialog "Hi!" buttons {"A", "B"}
end using terms from
Attempt 2
The application "dispD.app" is saved on the remote machine and should accept the yourMessage parameter.
on run {yourMessage}
display dialog yourMessage buttons {"A", "B"}
end run
I run this script from the local computer:
using terms from application "Finder"
set remoteFinder to application "Finder" of machine "eppc://user:password#host"
tell remoteFinder to run script file "path:to:my:dispD.app" with parameters {"Hi!"}
end using terms from
I think what you want to do may be impossible to do directly, although it's so hard to find docs on this that I'm not 100% sure. Various threads at MacScripter (such as this one) and on the Apple forums indicate a variety of problems talking to OSAXen ("Scripting Additions") over EPPC. (The threads get a bit confusing, because all of them diverge into red herrings, but I think some of them have relevant information.) And the "display dialog" command is not part of Finder (or System Events), it's part of the StandardAdditions OSAX.
This is actually hard to test from within AppleScript, because OSAX additions are pulled in automatically. But from appscript, you can manually attach an OSAX to an application like this:
sa = osax.ScriptingAddition('StandardAdditions', name='Finder')
sa.display_dialog('hi')
As expected, this works. while this gives an "unknown property, element, or command":
f = app(name='Finder')
f.display_dialog('hi')
Now, if I do an actual Finder command, like this:
f.windows()
Everything works. And if I want to remote that:
rf = app(url='eppc://test:test#localhost/Finder')
rf.windows()
No problem. But now:
sa = osax.ScriptingAddition('StandardAdditions', url='eppc://test:test#localhost/Finder')
sa.display_dialog('hi')
This works on 10.5, but not on 10.6, 10.7, or 10.8. (Well, out of the 8 machines I have access to, it works on the one that's running 10.5, but not on any of the 7 running 10.6+).
So, I think this is your problem.
As for solutions, I can think of a few hacky ways around this:
Instead of using remote scripting, use ssh + local osascript.
Use cocoadialog, pashua, etc., and drive them with do shell script, instead of using display dialog. (This will require you to have the respective tool on the remote target machine, not the local machine.)
Remote-script some app that can display dialogs natively, instead of relying on StandardAdditions. (I don't know if any of the stock apps have any way of doing this, so this might require installing something on the remote machine, in which case you might as well just use cocoadialog.)

Close App A when App B closes: Mac OS X 10.7.3

Say I have two applications running; App A and App B. What would be the easiest way (or indeed is there anyway) to get App B to close automatically when App A is closed? Note that neither of the apps in question have been developed by me and so I have no control over their internal behaviour.
I am open to any suggestions including those that entail the use of Applescript, Automator, Terminal commands and BASH scripting. I would even consider developing a lightweight Mac OS X application to achieve this.
If you don't need B to exit immediately - if it's OK to wait a few seconds - then you could schedule a periodic background task (using cron or even just iCal) that does something like this:
if not exists (processes where name is A)
tell application B to quit
end if
Another option, if you want an immediate response, would be to wrap App A in a script that launches it, waits for it to terminate, and then terminates B (osascript -e "tell application B to quit"). Then you could just always use that script to launch A.
You could even insert the script into the application bundle so that double-clicking runs your script. You would do this by doing "show package contents" on the application, replacing the <CFBundleExecutable> in <app>\Contents\info.plist with your script name, and dropping that script into <app>\Contents\MacOS. Then have the script just run the executable that is already there.
Fantastic question. I spent about 10 minutes looking for an old project where I had registered for notifications for when applications quit but couldn't easily find my code. But I did find a potential alternative for you.
If you download Apple's AppList sample code project, you'll see that it is observing the list of NSRunningApplications and when an app quits, it removes that app from the list of running apps in the window. You can take the technique they're using there and when you detect your "application A" quits, you can send a "quit" Apple Event to "application B".
Since you are running Lion, you can use a Cocoa-AppleScript to access Cocoa methods to add your application as an observer, getting notifications when applications quit.
For example, create a new application from the AppleScript Editor > File > New from Template > Cocoa-AppleScript applet. In the run handler, add the application as an observer to get notifications when an application quits:
set theNotice to current application's NSWorkspaceDidTerminateApplicationNotification
tell current application's NSWorkspace's sharedWorkspace's notificationCenter
addObserver_selector_name_object_(me, "appQuitNotification:", theNotice, missing value)
end tell
Next, add an appQuitNotification handler (this is the handler selector specified in addObserver_selector_name_object_ above), something like:
on appQuitNotification_(aNotification) -- an application quit
-- aNotification's userInfo record contains an NSRunningApplication instance that we can get properties from
set theApplication to (aNotification's userInfo's NSWorkspaceApplicationKey's localizedName()) as text
say "application " & theApplication & " quit" -- for testing
if theApplication is "this" then tell application "that" to quit -- or whatever
end appQuitNotification_
...and you are done. As long as your application is running, it will get notifications from the system when an application quits. Note that these Cocoa-AppleScript applications can't be run directly from the script editor, so they can be a bit of a pain to debug since there is no event log to look at - you will need to add your own dialogs or whatever.

Can a Cocoa app's executable steal focus from caller?

Say I have a standard Cocoa Application call Foo.app (like the one you get just by choosing New Project > Cocoa Application in Xcode), if I open the app via a terminal using:
open Foo.app/
Then I see Foo's name on the status bar up top and its window is in focus, in front of all other apps.
If instead I directly call from the terminal the executable buried in the .app folder, like:
Foo.app/Contents/MacOS/Foo
Nothing appears to happen. On inspection the app has indeed opened but it is not in focus (the terminal still is), I have to find it on the dock or find its window.
Is there any way for the Foo application to make sure its in focus when its run? Even if its run via its executable as described above?
Your app can "steal focus" by calling
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
See the NSApplication docs for more info.
did you mean to type:
open -a /Applications/Foo.app/
note the -a option
If you're asking how to give your app (that you're writing) this behavior -- within applicationWillFinishLaunching: you could call [NSApp activateIgnoringOtherApps:YES].
perhaps AppleScript?
tell application "TextEdit"
activate
end tell
There are (at least) three different ways you open (and interact with) Applications from the Terminal.
you can launch any Application (that is registered in LaunchServices) from the Terminal by typing open -a ApplicationName (note that you do not need the trailing ".app" or give any path)
you can open an application giving its specific path by typing open /path/to/ApplicationName.app (you will rarely need that, given that the applications is likely already registered in LaunchServices)
you can open and interact with the executable if you type open /path/to/ApplicationName.app/Contents/MacOS/ApplicationName. The difference here is that for some Applications, you can pass arguments or interact with them afterwards on your command line. Go ahead and try open /Applications/Mail.app/Contents/MacOS/Mail for example - it will give you a debugging log in return.
you can interact with some applications even without using "open" by directly calling their executable; try /Applications/Firefox.app/Contents/MacOS/firefox-bin —help for example.
So if you do want to make sure the command-line-launched application is in focus, use either method 1 or 2.

Application started by user or another application?

This is a very general question:
I was wondering whether it is possible to find out whether an application (any kind of application no matter if it a delphi-application or java or whatever) was started by a user or by another application? And if it is possible and I see that an application was called by another one, can I find out what the "father" application is, that called the new programm?
Thnx in advance!
EDIT: Maybe it is too general - How can I see whether a Delphi application has a parent application with Delphi itself, e.g. one application was started by a service and I need to find that service?
Every single running application has a parent application, which launched it (except for root system process).
It is not possible to tell, whenever it is user who directly clicked on application to lauch it or not.
Example: take Explorer shell (not Internet Explorer).
You can double click on any application to launch it. The parent process will be explorer.exe.
You can right-click on any file and a bunch of context menu extenders will load. Some of them may launch external applications to, say, create a preview of video-file (I saw this, swear!). The parent process will be explorer.exe, but user didn't indended to lauch any application. He just wants to view file's properties. He didn't even know, that applications were lauched!
Example: take Total Commander or any other two-panel file managers, which supports plugins for archives.
You can double click on any
application to launch it. The parent
process will be totalcmd.exe.
You may enter archive file and copy
(extract) few files from it to your
Documents folders. Corresponding
plugin may handle extraction by
itself or run invisible process to
handle all work. All you see is
progress bar in Total Commander. But
there is a new proces and its parent
is totalcmd.exe again.
There are no differences between cases 1 and 2 in both examples.
BTW, the definition "started by user" is unclear. You even may say that nothing can happen without user's command. All those background processes in cases #2 were launched because user asked for it. Well, user didn't asked for lauch explicitly, but he asked for operation itself.
You don't mention if you want to do this programmatically or if you're looking for a tool to just show the information.
If you just want to view the information, you can use Process Monitor, part of SysInternals:
http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx
In the Tools menu, there is a 'Process Tree' view that shows you a tree with parent / child process relationships and as well as the owner of each process.
If you want even more detail about processes, look at Process Explorer:
http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx
if it started by the user from windows so the parent will be explorer.exe, otherwise the parent will be the application which run the process.
to check the parent of a process by using tool check Ander Miller reply.
Did you see this question?
I'm not sure that I see problem right now.

Resources