Launch an NSTask and bring it to front

来源:互联网 发布:NSIS软件 编辑:程序博客网 时间:2024/05/17 04:42

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

objective-cnstask

share|improve this question

asked Feb 8 '11 at 0:39

d6d6e832034b6ee35ffecb3d66795e72.png

user549164

7810



4 Answers

active

oldest

votes

up vote

3

down vote

Don't use NSTask to launch applications. UseNSWorkspace, which has several methods (e.g.-launchApplication:) to launch and activate an application.

share|improve this answer

answered Feb 8 '11 at 1:21

1ebe99fd25ad376dad53b12322dd1337.jpg

indragie

7,209248104



 

There is a problem with using NSWorkspace I want to pass a file name as the argument in NSWorkspace functions if the app is already running meaning new instance is not created the argument part is ignored which makes it unusable in this scenario – user549164Feb 8 '11 at 1:47


 

Well in that case, maybe launch the app using NSTask and then use one of the NSWorkspace launching methods right after, because the NSWorkspace methods will bring the application to the front if it is already running. – indragieFeb 8 '11 at 3:30


 

@user549164: You can provide NSWorkspaceLaunchNewInstance to always launch a new instance, if that's appropriate. – PatrickMay 18 at 15:11

english-728.png

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([selfclass]),

                        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((constUInt8 *)[self UTF8String], anFSRef, NULL);

    if (status != noErr) {

        if (anError)

    *anError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil];

    }

    return (status == noErr);

}

@end

share|improve this answer

answered Feb 8 '11 at 13:17

NjKo2.png

NSGod

11.8k1232



up vote

0

down vote

If the task you want to launch is a proper application, you can use NSWorkspace's

  • (BOOL)openFile:(NSString *)fullPath withApplication:(NSString *)appName andDeactivate:(BOOL)flag

share|improve this answer

answered Feb 8 '11 at 3:52

71730cfb2f74b37c582cb764e6f800cf.png

jon

111



 

I've tried this but there seems to be a problem in passing arguments which have ' ' spaces int like a long file path with spaces. I tried passing in with quotes but the function returns an error – user549164Feb 8 '11 at 20:36


 

the app doesn't open file if there are spaces in filename –  user549164 Feb 8 '11 at 21:19

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];

share|improve this answer

edited Feb 8 '11 at 22:10



answered Feb 8 '11 at 3:53

d45a26aad5d401a93a4efcc31688d06c.png

Wevah

14.8k23643



 

NSWorkspaceLaunchConfigurationArguments is only available in 10.6 or later –  user549164 Feb 8 '11 at 21:06


 

Then you'll probably have to use launchAppWithBundleIdentifier:... and construct your own Apple Event to pass in the file. – WevahFeb 8 '11 at 22:06


 

Actually... [edits answer] –  Wevah Feb 8 '11 at 22:08


 

other app doesn't have a bundle identifier :( –  user549164 Feb 10 '11 at 0:01


 

Is it an older app? I don't think I've come across one without a bundle identifier in a while… – WevahFeb 10 '11 at 0:09

原创粉丝点击