Launch an NSTask and bring it to front
I'm trying to launch another application using NSTask
NSArray* argArray = [NSArray arrayWithObjects:fileName, nil];
NSTask* task = [NSTask launchedTaskWithLaunchPath:appName arguments:argArray];
while this works the main gui window doesn't come to front.
when repeatedly calling with different fileName the new file does get loaded in the app even though only 1 instance of the app is running
any poiners? I did try SetFrontProcess but seems to have no effect even after introducing a delay
I did look into NSRunningApplication but it seems it is not available on 10.5 whereas I need a solution for both 10.5 and 10.6
asked Feb 8 '11 at 0:39 7810 |
4 Answers
up vote 3 down vote | Don't use NSTask to launch applications. Use NSWorkspace, which has several methods (e.g. -launchApplication:) to launch and activate an application.
| ||||||||||||
|
|
up vote 1 down vote | I grabbed these from my MDFoundationAdditions and MDAppKitAdditions categories. This solution should work for Mac OS X 10.4.x and later (which is when LSOpenApplication() was introduced): MDAppKitAdditions.h: #import <Cocoa/Cocoa.h> #import "MDFoundationAdditions.h" @interface NSWorkspace (MDAdditions) - (BOOL)launchApplicationAtPath:(NSString *)path arguments:(NSArray *)argv error:(NSError **)error; @end MDAppKitAdditions.m: #import "MDAppKitAdditions.h" #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 #include <ApplicationServices/ApplicationServices.h> #elif MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 #include <CoreServices/CoreServices.h> #endif @implementation NSWorkspace (MDAdditions) - (BOOL)launchApplicationAtPath:(NSString *)path arguments:(NSArray *)argv error:(NSError **)error { BOOL success = YES; if (error) *error = nil; if (path) { FSRef itemRef; if ([path getFSRef:&itemRef error:error]) { LSApplicationParameters appParameters = {0, kLSLaunchDefaults, &itemRef, NULL, NULL, (argv ? (CFArrayRef)argv : NULL), NULL }; OSStatus status = noErr; status = LSOpenApplication(&appParameters, NULL); if (status != noErr) { success = NO; NSLog(@"[%@ %@] LSOpenApplication() returned %hi for %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), status, path); if (error) *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; } } } return success; } @end MDFoundationAdditions.h: #import <Foundation/Foundation.h> #import <CoreServices/CoreServices.h> @interface NSString (MDAdditions) - (BOOL)getFSRef:(FSRef *)anFSRef error:(NSError **)anError; @end MDFoundationAdditions.h: #import "MDFoundationAdditions.h" #import <sys/syslimits.h> @implementation NSString (MDAdditions) - (BOOL)getFSRef:(FSRef *)anFSRef error:(NSError **)anError { if (anError) *anError = nil; OSStatus status = noErr; status = FSPathMakeRef((const UInt8 *)[self UTF8String], anFSRef, NULL); if (status != noErr) { if (anError) *anError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; } return (status == noErr); } @end
| ||
| |
up vote 0 down vote | If the task you want to launch is a proper application, you can use NSWorkspace's
| ||||||||
|
|
up vote 0 down vote | To expand on indragie's answer, if you want a new instance launched with a file argument, do something like (untested): NSDictionary *config = [NSDictionary dictionaryWithObjectsAndKeys: [NSArray arrayWithObject:filePath], NSWorkspaceLaunchConfigurationArguments, nil]; NSError *error = nil; [[NSWorkspace sharedWorkspace] launchApplicationAtURL:yourAppURL options:NSWorkspaceLaunchNewInstance | NSWorkspaceLaunchDefault configuration:config error:&error] On 10.5, you might try (not tested): NSURL *fileURL = [NSURL fileURLWithPath:filePath]; [[NSWorkspace sharedWorkspace] openURLs:[NSArray arrayWithObject:fileURL] withAppBundleIdentifier:@"com.foo.someapp" options:NSWorkspaceLaunchNewInstance | NSWorkspaceLaunchDefault additionalEventParamDescriptor:nil launchIdentifiers:nil];
| ||||||||||||||||||||
|
|