5. Finding and Targeting Applications
The AEMApplication class
The AEMApplication class represents an application to which Apple events will be sent. Applications may be identified by: name, bundle ID, Unix process ID, file URL, eppc URL, any AEAddressDesc, or the host process. Its main method, -eventWithEventClass:eventID:returnID:codecs: (several shortcuts are provided for convenience), is used to construct the Apple events to send. Utility class methods are also provided for locating application files, checking if an application process exists, and launching applications.
@interface AEMApplication : NSObject
/*
* The target application
*/
// Find application files:
// (Note: these methods are normally used internally by initializers,
// but may be used by external clients if needed.)
+ (NSURL *)findApplicationForCreator:(OSType)creator
bundleID:(NSString *)bundleID
name:(NSString *)name
error:(NSError **)error; // may be nil
/*
* Find application by one or more of the following:
* - creator code (e.g. 'ttxt'); use kLSUnknownCreator if none
* - bundle ID (e.g. @"com.apple.textedit"); use nil if none
* - file name (e.g. 'TextEdit.app'); use nil if none.
*
* (Convenience wrapper for LaunchServices' LSFindApplicationForInfo
* function.)
*/
/*
* Find application by file name.
*
* Notes:
* - A full path is also acceptable.
*
* - The .app suffix is optional; if not given, the method first looks
* for an exact file name match, and if none is found it searches for
* the same name with an .app suffix appended.
*/
+ (NSURL *)findApplicationForName:(NSString *)name
error:(NSError **)error;
// Check if a process exists:
+ (BOOL)processExistsForFileURL:(NSURL *)fileURL;
/*
* Does a local process launched from the specified application file
* exist? e.g. [NSURL fileURLWithPath: @"/Applications/iCal.app"]
* Returns false if process doesn't exist or file isn't found.
*/
+ (BOOL)processExistsForPID:(pid_t)pid;
/*
* Is there a local application process with the given Unix process id?
*/
+ (BOOL)processExistsForEppcURL:(NSURL *)eppcURL;
/*
* Does an application process specified by the given eppc URL exist?
* e.g. [NSURL URLWithString: @"eppc://user:pass@0.0.0.1/TextEdit"]
* Returns false if process doesn't exist, or if access isn't allowed.
*/
+ (BOOL)processExistsForDescriptor:(NSAppleEventDescriptor *)desc;
/*
* Does an application process specified by the given AEAddressDesc exist?
* Returns false if process doesn't exist, or if access isn't allowed.
*/
// Launch an application:
+ (pid_t)launchApplication:(NSURL *)fileURL
event:(NSAppleEventDescriptor *)firstEvent
flags:(LaunchFlags)launchFlags
error:(NSError **)error; // may be nil
/*
* Launch a local application.
*
* (Convenience wrapper for Process Manager's launchApplication function.
* See Process Manager documentation for possible error codes.)
*/
// Convenience shortcuts for the above; these supply the appropriate
// first event along with the launchContinue, launchNoFileFlags and
// launchDontSwitch flags:
+ (pid_t)launchApplication:(NSURL *)appFileURL
error:(NSError **)error; // may be nil
+ (pid_t)runApplication:(NSURL *)appFileURL
error:(NSError **)error; // may be nil
+ (pid_t)openDocuments:(id)files // an ASAlias/NSURL or NSArray thereof
inApplication:(NSURL *)appFileURL
error:(NSError **)error; // may be nil
// Initializers:
- (id)initWithName:(NSString *)name;
- (id)initWithName:(NSString *)name
error:(NSError **)error; // may be nil
/*
* Init with application's filename, e.g. @"TextEdit.app"
* Application is located via LaunchServices.
* (See LaunchServices documentation for possible error codes.)
* Note: This will start application if not already running.
*/
- (id)initWithBundleID:(NSString *)bundleID;
- (id)initWithBundleID:(NSString *)bundleID
error:(NSError **)error; // may be nil
/*
* Init with application's bundle ID, e.g. @"com.apple.textedit"
* Application is located via LaunchServices.
* (See LaunchServices documentation for possible error codes.)
* Note: This will start application if not already running.
*/
- (id)initWithURL:(NSURL *)url;
- (id)initWithURL:(NSURL *)url
error:(NSError **)error; // may be nil
/*
* Init with file URL or eppc URL, e.g.
* [NSURL fileURLWithPath: @"/Applications/TextEdit.app"],
* [NSURL URLWithString: @"eppc://user:pass@0.0.0.1/TextEdit"]
*
* Note: If a file URL is given, this will start application if not
* already running.
*
* (See Process Manager/Apple Event Manager documentation for possible
* error codes.)
*/
- (id)initWithPID:(pid_t)pid;
/*
* Init with Unix process ID.
*/
- (id)initWithDescriptor:(NSAppleEventDescriptor *)desc;
/*
* Init with AEAddressDesc.
*/
- (id)init;
/*
* Init with current (i.e. host) process.
*/
// Create Apple events (see next chapter for details):
- (id)eventWithEventClass:(AEEventClass)classCode
eventID:(AEEventID)code
returnID:(AEReturnID)returnID
codecs:(id)codecs;
- (id)eventWithEventClass:(AEEventClass)classCode
eventID:(AEEventID)code
returnID:(AEReturnID)returnID;
- (id)eventWithEventClass:(AEEventClass)classCode
eventID:(AEEventID)code
codecs:(id)codecs;
- (id)eventWithEventClass:(AEEventClass)classCode
eventID:(AEEventID)code;
@end
Creating AEMApplication objects
When targeting a local application by name, bundle ID or file URL, note that aem identifies the application by process ID for reliability. If the target application is not already running when a new AEMApplication instance is created, it will be started automatically so that a PID can be acquired.
If the -initWithURL:error: initializer is passed an eppc URL string, aem will pack this as an AEDesc of typeApplicationURL. The target machine must have Remote Apple Events enabled in its Sharing preferences.
Clients can also supply their own AEAddressDesc if they prefer. This should be an NSAppleEventDescriptor of one of the following types:
typeApplicationBundleID
typeApplicationURL
typeApplSignature
typeKernelProcessID
typeMachPort
typeProcessSerialNumber
See the Apple Event Manager documentation for more information on these addressing modes.