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.)
Related
I know how to list all window titles in Windows, for example using Python via the Win32 API. Or eventually I could write it in C/C++ directly.
How do I accomplish this for Mac OS X? It doesn't necessarily have to be in Python, and it doesn't have to be cross-platform. Preferably it would run without requiring any additional downloads (like an applescript file or a bash file using included commands only), but that's not required.
Probably the simplest way of doing this "with no additional downloads" is to use AppleScript:
tell application "System Events"
get name of every window of every process
end tell
Since the Applescript syntax is pretty obtuse, the equivalent Javascript is:
var SE = new Application("System Events");
SE.processes.windows.name()
This will return a structure of the form:
[[], [], ["Stack Overflow"], ["iTunes", "MiniPlayer"], ...]
where each array entry represents one running application, and each string within those arrays represents one window. Empty arrays indicate applications with no open windows.
(Note that this Javascript must be run in Script Editor, not in a web browser. Components of the Scripting Bridge, including System Events, are not available from web browsers.)
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.
We have a script to send email using Microsoft outlook or Apple mail application. It will dynamically load the default email from system preference (maybe user input also), and using it to decide which mail client to use.
So the code is as following:
if (mailClientStr contains "outlook")
tell application id "com.microsoft.outlook"
-- <<< there will be error if there is no outlook installed
-- <<< even else branch will be run.
...
end tell
else
tell application id "com.apple.mail"
...
end tell
end if
On an machine which doesn't have outlook installed, and the mailClientStr will be "com.apple.mail", but this script cannot be run by osascript
It complains Can’t get application id "com.microsoft.outlook" even the first branch will not be executed. My understanding is osascript will need to access Outlook apple script interface when load and compile this script (before run it).
I can separate the outlook related code into a separate script, but because there is a lot of data to passing, it will be complex, so I don't want this workaround.
So does there any solution from the apple script language side?
From the AppleScript Language Guide:
Entering Script Information in Raw Format
You can enter double angle brackets, or chevrons («»), directly into a script by typing Option-Backslash and Shift-Option-Backslash. You might want to do this if you’re working on a script that needs to use terminology that isn’t available on your current machine—for example, if you’re working at home and don’t have the latest dictionary for a scriptable application you are developing, but you know the codes for a supported term.
You can also use AppleScript to display the underlying codes for a script, using the following steps:
Create a script using standard terms compiled against an available application or scripting addition.
Save the script as text and quit Script Editor.
Remove the application or scripting addition from the computer.
Open the script again and compile it.
When AppleScript asks you to locate the application or scripting addition, cancel the dialog.
Script Editor can compile the script, but displays chevron format for any terms that rely on a missing dictionary
I'm trying to make two copies of an AppleScript, one that works for Entourage and one for out Outlook. I only have Entourage installed on the current computer.
According to the info on Microsoft's site, both applications have the same library of AppleScript commands, and I should be able to simply change the application name referenced within the script.
Changing:
Tell application "Microsoft Entourage"
to
Tell application "Microsoft Outlook"
Prevents me from saving the script because I don't have outlook installed on this computer. Is there any way around this? Do I need to use a text editor to edit the actual script file and change it there?
Thanks!
The following work-around may do the trick. On the computer where Entourage is installed, a using terms directive will let you compile the script, even if Outlook is not installed:
set theApp to a reference to application "Microsoft Outlook"
using terms from application "Microsoft Entourage"
tell theApp
get version
...
end tell
end using terms from
Upon compiling and saving the script the AppleScript Editor will bug you about the missing Outlook application, but it will nevertheless produce a compiled AppleScript file (.scpt).
Applescript is a pre-complied file format, meaning that every time you click "Save" it runs through a series of steps to ensure the script will work, but just short of actually running through the script's logic. Part of those steps is to look for the application to see if it exists on the Mac.
In short, if you want to save the script as an Applescript, you need the target application installed, otherwise you can save the script as a text file and move the file over to the target Mac to save as an Applescript over there.
It should be possible to make one script that works with both Entourage and Outlook, without bugging you if one isn't found either when you compile or when you run. I don't have either Entourage or Outlook but it should work like this:
using terms from application "Microsoft Entourage"
script theScript
tell application "Finder" to try
set theApp to application file id "Entourage's Bundle ID" as text
on error
set theApp to application file id "Outlook's Bundle ID" as text
end try
tell application theApp
-- do stuff
end tell
end script
end using terms from
store script theScript in "MyScript.scpt"
"using terms from" is only relevant when compiling the script - it isn't needed when running, though for some reason you'll still get bugged if that app isn't found. So by wrapping it around a script object and then writing out that script to file, the resultant script will still run but won't contain "using terms from" and so won't bug the user.
For getting a reference to the right app, Finder can look for it by ID and simply error if it isn't found rather than bugging the user. You'll need to insert the proper ID's there, I don't know what they are.
I'm currently writing an applescript to be run within FileMaker. I need to tell filemaker what the name of its application is (FileMaker Pro or FileMaker Pro Advanced or whatever) so that I can within ANOTHER applescript within filemaker I can say "tell application filemaker"
I currently have a script that figures out the name of the app file, however, the problem is getting it back into filemaker. The name I want to send back is in the applescript variable "FMName" I can think of 2 options
1)
tell application FMName
set cell "gFMName" of current record to FMName
end tell
The problem with this is that even though I know that application FMName will have a set cell command, applescript doesn't and so complains.
2) have the applescript either return a value or an error message and somehow get FileMaker to accept this and do something useful with it.
The problem with this is that 1)it appears that Applescripts can only return numbers (is this true?) 2) I don't want an error dialog or anything, and 3) I have not figured out how to get filemaker to accept this return value in the first place...
Anyone have any better ideas on how to do this?
Thanks!
I know this thread is a bit stale now, but here's what I do - use an if statement. Use the Get(ApplicationVersion) function to find out what kind of FileMaker is running:
If ( PatternCount ( Get ( ApplicationVersion ) ; "Advanced" ) ;
"tell application \"FileMaker Pro Advanced\"" ;
"tell application \"FileMaker Pro\"" )
I have taken this a step further and set it up as a custom function so I don't have it repeated in many different scripts.
Since (if I understand you correctly) no matter what the application is that's being targeted, it's a version of FileMaker, whether FileMaker Pro or FileMaker Pro Advanced or even a runtime version of FileMaker, the dictionary being used will have the same terms available. So, you could use the using terms from application "FileMaker Pro" to enclose the block that you want to execute.
using terms from application "FileMaker Pro"
tell application FMName
set cell "gFMName" of current record to FMName
end tell
end using terms from
I haven't experimented with it, so am not sure if it will work. It seems your goal is to get one FileMaker application to receive data from the AppleScript in another FileMaker application. I do wonder, however, why you're using two FileMaker applications. Are they different versions (i.e., FileMaker 10 and FileMaker 6)? If so, perhaps having the AppleScript write the data to a file that the second FileMaker application then imports is an option. But if they are both FileMaker 7-10, why not simply open the two files in the same application? Then you can write the data from AppleScript directly to the correct file.
This was answered but I though I would add something I discovered lately.
If you target another app, say the Finder, with a "Tell application Finder Activate" then those FMP calls will fail because your now IN the Finder till you do an "End Tell" or explicitly point back to FMP.
The solution that was pointed out to me was to do the out side calls in a single line such as
"Tell application Finder to [what ever you needed the Finder to do]"
This directs just that tell to the non FMP application but leaves you still IN FMP so your FMP calls will work.
This becomes an issue with runtimes since the runtime name will be different from your development application name.