AppleScript: Making your application scriptable

From REALbasicWiki

Jump to: navigation, search

 Available on Mac OS only  This article applies only to Mac  

Contents

[edit] Step by Step

[edit] Making the 'aete' resource:

1. I started ResFool and in the menu bar, I created a new resource under Resource>New Resource...

2. I selected "aete" from the list and ResFool gave a default ID of 128. I changed that to 0 per James' instructions. For the resource name, I entered "RB Message Suite".

3. I double-clicked on the resource, and the resource editor window appeared. I clicked the "Add" button to create a new Suite with the following properties:

NAME: "Message Suite" CODE: "RBMS"

4. ResFool then defaulted to the Events tab, and I clicked "Add" and gave the new event the following properties:

NAME: "showText" (this is the command as it will appear in the Applescript). CLASS: (It defaults to the container Suite, I left it as is) ID: "show"

5. I saved the resource file under the name "Resources". ResFool adds the .rsrc extension by default, so I removed that.


[edit] Making the RB application:

1. I created a new Desktop Application.

2. For the App class, I gave it the following properties in the Properties pane:

MacOSXAppName: "Optimus" MacCreator: "Opti" Bundle Identifier: "com.OandC.Optimus"

3. I dragged the resource file into the Project tab of the IDE.

4. In the App.HandleAppleEvent event, I placed the following code:

  select case eventClass
  case "RBMS" //Message Suite
    select case eventID
    case "show" //showText
      MsgBox "Optimus!"
    else
      return false
    end select
  else
    return false
  end select
  return true

5. I built the app as a Universal Binary.

6. Back in the Finder, I right-clicked on the application and selected "Show Package Contents". I went into the Contents folder and double-clicked the "Info.plist" file to open it in the Property List Editor.

7. In the Info.plist file I added the following child to the root, saved the file, and quit:

NSAppleScriptEnabled as Boolean = "YES"

8. At this point the application was ready for scripting. I closed the window and ran the application.

[edit] Writing the Applescript:

1. I opened the Script Editor and selected File>Open Dictionary... Optimus.app was visible in the list. The dictionary appeared just like any other.

2. In the editor, I entered the following script:

tell application "Optimus"
	showText
end tell

I saved, ran, and I got the dialog window in my RB app with the text in place. It did exactly what I wanted it to.

[edit] Tips, Gotchas, and Miscellaneous Comments

[edit] Helper Applications

All applications were tested in Mac OS 10.4.11 and 10.5.2. Opinions are strictly those of the author (Philip Regan 09:58, 21 May 2008 (EDT))

[edit] Rezilla

  • Free and open source
  • Very funky interface and with large Applescript libraries becomes almost useless
  • Might have a problem properly saving (and subsequently reopening) its own files.

[edit] ResFool

  • Fully working demo and closed source with a 10 second nag window on file saving.
  • Similar interface to Rezilla, but much more user friendly.

[edit] sdef Editor

  • Free and closed source.
  • Written with Leopard in mind and offers a great interface.
  • Support is quick to update for bugs
  • Documentation is limited, but offers a nice intro to the purpose of different properties and fields.

[edit] Naming classes and IDs

It looks as though Apple has a variety of classes and IDs already reserved. The easiest to read lists are in ResFool and sdef Editor (in the form of the example libraries). At the same time, I think the developer has full control of the "object library", so they can be named pretty much anything. Because the class and IDs are limited to four (4) ASCII characters each, the same legal characters as Creator Codes. The challenge here is to create codes that make at least some semblance of sense to the developer. It's a hassle, to be sure, but just consider it good practice for efficient variable naming.

[edit] About Verbs

All Class and ID codes are four characters except for verbs which are eight characters for the Class and nothing for the ID. However, the first four characters of the verb Class code is usually the containing Suite. (Some of the examples offered by Apple show "misc" in the "aevt" (AppleEvent) Suite).

ResFool and Rezilla keep the two codes in seperate fields. sdef Editor has you enter the Class and ID codes into separate fields, but then they can be both entered into the Class field as well. There might be a bug related to this in that the code won't be recognized and any Applescript that calls the event will fail silently as a result. The built-in check function for sdef Editor returns an error regardless of how they were entered, and with RB's sdef support undocumented at this point, it's tough to say which one is the correct way of handling it.

[edit] Source Materials

[edit] From the NUG

[edit] Posted by Philip Regan:

This topic has been bandied about quite a bit lately, and I have a need to do it myself. However, my day has been long and difficult with little to show for it. I know a few have done this, and a few of those claim great success, but no one is really forthcoming with detailed information, and I've come to a standstill. So, the purpose of this thread is twofold. The first is to hopefully sort just what it is that I'm doing wrong. The second is to (alos hopefully) create The Ultimate Applescript Implementation Thread so that all of the niggling details will be documented in one place...

From all of the information I have gathered through here, the NUG, here, RBDev, and other resources, there are two ways to do this, and neither of them work for me. I've even tried this on both 10.4 and 10.5.

Method 1: The "aete" file. From what I can gather, this is the OS 7-9 method of adding Applescript, but I thought I would give it a go anyway. I've been using Rezilla to create the .rsrc files necessary.

Here are the steps I've been taking:

I create a new resource with these properties Type: aete ID: 0 Name: Applescript Support

In the new resource I create a new Suite with the following properties: Name: Test Suite ID: RBtx Level: 0

In the new suite I create a new Event with the folloing properties: Name: showText Class: RBtx ID: DsMs Parameters: None needed for the test method in the RB app.

I save the file as "resources.rsrc" and drag it into the Project tab of the IDE.

I build the application (not just debug run) and using Apple's Property List Editor, I add the following property:

NSAppleScriptEnabled as Boolean = "YES"

The one thing that keeps tripping me up time and time again is that when Ibuild my app, RB isn't copying the resource file into the Resources folder of the application bundle. If I manually copy the file in there, I don't get anything.

Script Debugger recognizes the application as being scriptable. But when I go to view the dictionary, Script Debugger presents me with an empty dictionary, and Script Editor doesn't do anything. If I open the .rsrc file in directly Script Debugger or Script Editor by drag and drop on the icon, I can view the file as a Dictionary.

Method 2: The "sdef" file. This looks to be the preferred method to add a dictionary and capability in OS X because and sdef is merely an XML file with a ".sdef" extension.

I've been duplicating the same settings as I have with the "aete" method because I it looks as though a lot hasn't changed, and if it has changed, then documentation is hard to find or beyond my skill level to comprehend.

I've been using Sdef Editor from Shadow Labs,and have gone through the example sdef files they have in the app that are supposed to be Apple's own examples. I've followed them as closely as I could to be sure I didn't miss anything including combining the Class and ID parameters. I'll also tried saving the file with the same name as the ".rsrc" and ".sdef" for the extension, but that resulting in more problems than anything.

When I build the app, *sometimes* I can see the dictionary, but again, when I enter the command, the script editor views it as a variable and not a command.

Now, to troubleshoot all of this based on the various bits of information I've found, I've saved both of the ".sdef" and ".rsrc" files at the same name as the application and with their own unique names. I get the same results.

In the one instance that I could get the script editors to view the dictionary properly (and I have no idea how that happened), when I entered the command into the Applescript and compiled, it saw the command as a variable and gave the appropriate (yet incorrect) error that the variable hasn't been set.

The resources I've found:

http://forums.realsoftware.com/viewtopic.php?f=7&t=22001&p=116522&hilit=+Applescript#p116522

http://tooloo.de/rb/ApplScriptTest.dmg

http://forums.realsoftware.com/viewtopic.php?f=7&t=15145&p=82485&hilit=+Applescript#p82485

http://www.rbdeveloper.com/browse/1.5/1515/

http://www.declaresub.com/wiki/index.php/AppleScript:_How_to_add_AppleScript_capability_to_your_RB_app

Rezilla: http://sourceforge.net/projects/rezilla

Resfool: http://www.versiontracker.com/dyn/moreinfo/macosx/22145&vid=141704

Sdef Editor: http://www.shadowlab.org/Software/sdefeditor.php

So, that's all of my cards at the table, and I'm to the point of flailing here, and I absolutely have to get this to work. I'm already at Plan C for this project, and this is just creating a dummy app to see if I can do it. I haven't even gotten to the actual coding on this portion of my project.

Any help anyone has, particularly those who have been successful at this, would be greatly appreciated.

Cheers -- Philip Regan http://www.oatmealandcoffee.com Mac OS 10.5.2, RB2008r2


[edit] Posted by James Sentman:

OK this is great, lets make this the goto place for info. Then munge it all into the wiki or someplace.

I can add a couple of things to help get started.

First you have to have a MacCreator and/or (or? maybe but I always do both) bundle identifier before the system will recognize that your app is scriptable.

I don't know about script debugger, but the script editor caches it's database information and if you make a change to an app's dictionary (or just add one) you must quit and restart it before it will notice anything changed.

If you're adding an aete resource the ID is important too. In my files where it works the ID is 0. Some editors default to 128 as the resource ID and that seems to confuse things.

RB will recognize a file called "Resources" with no file extension and include the resources in the app if you drag it into the project, perhaps your creating it with a .rsrc file extension or something?

As far as editing, resfool is my favorite aete editor on OSX, there is a freeware one out there that I forget the name of but the last time I looked it used a non-live updating slider to scroll through your entries so as your database grew large you had to scroll through manually looking for the one you wanted rather than choosing from a list. This made it completely unusable to me. Perhaps the freeware one has been updated, or perhaps there are others now.

As far as aete vs sdef, the last time I looked (which was probably in 10.3 timeframe) it was still necessary to have an aete file for a carbon type app as you had to enter cocoa entry points in the sdef file? I could be remembering that wrong, but there was a good reason why an RB app had to use an aete and not an sdef. There is an sdef to aete converter provided by apple but it doesn't do very many special things and choked on most of what was in the dictionary of my most complicated app. It supports only a small subset of possible variable types doe instance. Unless additional functionality has been added to the sdef format in the meantime it will probably be necessary for an RB app to have an aete resource. There is a way to create these on the fly and send them to the system (which is why some apps have to launch before you can get their scripting dictionary) but i dont know how to do this ;) There was a fellow who wrote a plugin to handle some of this back in the really really old dark ages that I had a copy of for a while and experimented with. This would allow for things like updating the dictionary as the capabilities or contents of your program changed. This would be cool to figure out.

Once you get it working there are a bunch of gotchas that we need to look out for like the fact that enumerated params are backwards on Intel, and in 10.5 all strings coming from or going to an applescript are going to be forced 4 byte UTF16 and will need to be converted to UTF8 for easy and reliable use inside of XTension. There is still no date handling but this can be done by creating " ldt" descriptors in code via declares. It is also possible to support a subset of the object model, but becomes very complicated quickly. Perhaps someone that has experience with doing this from C could chime in or contact me off the list so we could mix together what I know about getting the data in RB and what you know about what it's supposed to be to make it easier to parse out ;) Just handling regular verbs is fairly straight forward once you get all the rest working.

Thanks,

James

James Sentman [1] [2]


[edit] Posted by Philip Regan:

on May 20, 2008, at 12:18, James Sentman wrote:

> OK this is great, lets make this the goto place for info. Then munge > it all into the wiki or someplace. > > I can add a couple of things to help get started. > > First you have to have a MacCreator and/or (or? maybe but I always do > both) bundle identifier before the system will recognize that your app > is scriptable.

This is the first I've see that bit of information, just as an example how sketchy info about this is.


> If you're adding an aete resource the ID is important too. In my files > where it works the ID is 0. Some editors default to 128 as the > resource ID and that seems to confuse things. > > RB will recognize a file called "Resources" with no file extension and > include the resources in the app if you drag it into the project, > perhaps your creating it with a .rsrc file extension or something?

Yes, I was, but other applications have their files with different names and the .rsrc extension as well as some that have .scriptSuite (?). I figured if it was okay for them then I could get away with it ("resources" isn't the most descriptive file name) but I guess not.


> As far as editing, resfool is my favorite aete editor on OSX, there is > a freeware one out there that I forget the name of but the last time I > looked it used a non-live updating slider to scroll through your > entries so as your database grew large you had to scroll through > manually looking for the one you wanted rather than choosing from a > list. This made it completely unusable to me. Perhaps the freeware one > has been updated, or perhaps there are others now.

Rezilla is the one with the funky interface, but it is free and open source. No nagging shareware window. I think it also it has been updated more recently than ResFool.


> [snip]...Just handling regular verbs is fairly straight > forward once you get all the rest working.

That's all I need to do for now. I'll try it again with this new information and post the results.

Thanks -- Philip Regan http://www.oatmealandcoffee.com Mac OS 10.5.2, RB2008r2

Personal tools
related