|
This Technote describes the API that allow developers to create AppleScript scripting additions for Mac OS X. It is directed at application developers who are interested in creating scripting additions. What are Scripting Additions?Scripting additions provide a mechanism for delivery of additional functionality that can be used in AppleScripts. A scripting addition can provide Apple event handling and Apple event data coercion handling. The Apple event handlers and Apple event data coercion handlers installed by a scripting addition are written in basically the same way that handlers used inside an application are written. What differs between scripting additions and applications is the packaging of the code and the mechanisms by which the scripting addition is installed in the system. These differences are discussed in the sections that follow. Packaging Scripting AdditionsScripting additions are packaged as bundles with a name ending with the extension Note: Single-file CFM binaries linked with Mac OS X version 10.5 (Leopard): Info.plistMac OS X version 10.5 (Leopard) introduces a new data-driven scheme for installing the handlers in a scripting addition. It is optional, but recommended since it is simpler to write and faster to load, which affects Applescript's initialization time. The
The value in each case is a dictionary whose keys are the eight-character event code (event class and event id) or the "from" and "to" Listing 1: Info.plist fragment declaring scripting addition functions. <key>OSAXHandlers</key> <dict> <key>Events</key> <dict> <key>sysodlog</key> <string>DisplayDialogEventHandler</string> </dict> <key>DescCoercions</key> <dict> <key>STXTutxt</key> <string>CoerceStyledTextToUnicodeText</string> </dict> <key>PtrCoercions</key> <dict> <key>TEXTutxt</key> <string>CoercePlainTextToUnicodeText</string> </dict> </dict> All of the functions named must be exported as entry points into the executable. Given this data, the system will take care of installing and uninstalling the handlers for you: there is no initialization or cleanup for you to write. Mac OS X version 10.4 (Tiger) and earlier: Required FunctionsIf your scripting addition will only run on Leopard or later versions, then this Info.plist entry is all you need. If you want it to run on older versions of Mac OS X, then you must supply three additional functions to install, terminate, and reference-count your scripting addition. Note: When running in Leopard, the initialization function will only be called if you do not provide the Info.plist data described above. The reference-count function will never be called, since Leopard will never attempt to unload a scripting addition from a process once it is loaded. The termination functions will also never be called. If your addition needs to do work at process termination time, such as releasing resources, use InitializationYour scripting addition's initialization routine is responsible for installing your scripting addition's handler routines. To implement it, the scripting addition must export a routine named Listing 2: Sample scripting addition initialization routine. OSErr SAInitialize(CFBundleRef additionBundle) { OSErr err; Boolean isSysHandler = true; err = AEInstallEventHandler(theAEEventClass, theAEEventID, eventHandlerUPP, refcon, isSysHandler); err = AEInstallCoercionHandler(fromType, toType, coercionHandlerUPP, refcon, fromIsDesc, isSysHandler); return err; } All scripting addition handlers must be installed in the system dispatch table, as shown above. IMPORTANT: If your initialization routine returns any result other than Your scripting addition should always install all of its handlers, even if functionality they require is not present in the system. That way, you have an opportunity to provide a meaningful error message when your addition is invoked, rather than the generic "doesn't understand" or "can't coerce" message. Your initialization function may perform additional setup operations, such as allocating memory or finding files, but this is not recommended: it creates additional startup cost, and may not even be necessary, since your scripting addition may never be invoked. Initialization should be deferred until your addition is actually invoked. The Information about bundle references and the bundle format can be found in the References section at the end of this article. TerminationYour scripting addition's termination routine is responsible for removing your scripting addition's handler routines. To implement it, a scripting addition must export a routine named Listing 3: Sample scripting addition termination routine. void SATerminate(void) { AERemoveEventHandler(theAEEventClass, theAEEventID, gTheHandler, true); DisposeAEEventHandlerUPP(gTheHandler); ...other cleanup operations... } The termination routine may perform other cleanup operations, such as releasing resources. However, the termination function will never be called in Leopard. If your addition needs to do work at process termination time, such as releasing resources, use Reference CountingThis routine exists for historical reasons: in classic Mac OS, it was possible to crash the system by removing a scripting addition while it was still running. Therefore, scripting additions exported a function named Listing 4: Sample SAIsBusy routine for a scripting addition. Boolean SAIsBusy(void) { return false; } Helpful TipsRuntime ConsiderationsYour scripting addition may be loaded into any application's process, and should therefore take care to not disturb the global state outside of the addition handler itself, such as the Resource Manager resource chain, effective user id, and so on. Scripting additions are loaded separately into each application process that uses them. As a result, you should design your scripting addition keeping in mind that there may be many instances of your scripting addition open in many different applications at the same time. Some scripting additions may require additional code if they use a single shared resource such as a printer or a serial port. Locating Your Scripting Addition's Bundle ResourcesScripting additions may need to access resources and files located inside of their bundle. To do this, get a Information about bundle references and the bundle format can be found in the References section at the end of this article. Local and Remote RequestsEach of your scripting addition's handler routines is responsible for detecting and rejecting events from remote systems, if appropriate, typically because the command would constitute a security risk. A handler can determine the source of an event by examining the DescType sourceAttr; err = AEGetAttributePtr(eventPtr, keyEventSourceAttr, typeType, NULL, &sourceAttr, sizeof(sourceAttr), NULL); if (err == noErr && sourceAttr == kAERemoteProcess) { return errAEEventNotHandled; } ReferencesDownloadables
Document Revision History
Posted: 2008-04-24 |
|