Запустите NSTask и выведите его на передний план.

Я пытаюсь запустить другое приложение с помощью NSTask

NSArray* argArray = [NSArray arrayWithObjects:fileName, nil];
NSTask* task = [NSTask launchedTaskWithLaunchPath:appName arguments:argArray];

пока это работает, главное окно графического интерфейса не появляется.

при повторном вызове с другим именем файла новый файл загружается в приложение, даже если запущен только 1 экземпляр приложения.

любые указатели? Я пробовал SetFrontProcess, но, кажется, не имеет никакого эффекта даже после введения задержки

Я просмотрел NSRunningApplication, но, похоже, он недоступен в 10.5, тогда как мне нужно решение как для 10.5, так и для 10.6.


person user549164    schedule 08.02.2011    source источник


Ответы (4)


Не используйте NSTask для запуска приложений. Используйте NSWorkspace. , который имеет несколько методов (например, -launchApplication:) для запуска и активации приложения.

person indragie    schedule 08.02.2011
comment
Существует проблема с использованием NSWorkspace. Я хочу передать имя файла в качестве аргумента в функциях NSWorkspace, если приложение уже запущено, что означает, что новый экземпляр не создан, часть аргумента игнорируется, что делает его непригодным для использования в этом сценарии. - person user549164; 08.02.2011
comment
Что ж, в этом случае, возможно, запустите приложение с помощью NSTask, а затем сразу после этого используйте один из методов запуска NSWorkspace, потому что методы NSWorkspace выведут приложение на передний план, если оно уже запущено. - person indragie; 08.02.2011
comment
@ user549164: Вы можете указать NSWorkspaceLaunchNewInstance, чтобы всегда запускать новый экземпляр, если это уместно. - person Patrick Pijnappel; 18.05.2013

Я взял их из своих категорий MDFoundationAdditions и MDAppKitAdditions.

Это решение должно работать для Mac OS X 10.4.x и более поздних версий (когда была введена LSOpenApplication()):

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
person NSGod    schedule 08.02.2011

Чтобы расширить ответ Индраги, если вы хотите, чтобы новый экземпляр запускался с аргументом файла, сделайте что-то вроде (непроверено):

NSDictionary *config = [NSDictionary dictionaryWithObjectsAndKeys:
                         [NSArray arrayWithObject:filePath], NSWorkspaceLaunchConfigurationArguments,
                         nil];
NSError *error = nil;
[[NSWorkspace sharedWorkspace] launchApplicationAtURL:yourAppURL options:NSWorkspaceLaunchNewInstance | NSWorkspaceLaunchDefault configuration:config error:&error]

В 10.5 вы можете попробовать (не проверено):

NSURL *fileURL = [NSURL fileURLWithPath:filePath];
[[NSWorkspace sharedWorkspace] openURLs:[NSArray arrayWithObject:fileURL] withAppBundleIdentifier:@"com.foo.someapp" options:NSWorkspaceLaunchNewInstance | NSWorkspaceLaunchDefault additionalEventParamDescriptor:nil launchIdentifiers:nil];
person Wevah    schedule 08.02.2011
comment
NSWorkspaceLaunchConfigurationArguments доступен только в версии 10.6 или более поздней. - person user549164; 09.02.2011
comment
Тогда вам, вероятно, придется использовать launchAppWithBundleIdentifier:... и создать собственное событие Apple для передачи в файл. - person Wevah; 09.02.2011
comment
другое приложение не имеет идентификатора пакета :( - person user549164; 10.02.2011
comment
Это старое приложение? Я не думаю, что когда-либо сталкивался с одним без идентификатора пакета… - person Wevah; 10.02.2011

Если задача, которую вы хотите запустить, является правильным приложением, вы можете использовать NSWorkspace

- (BOOL)openFile:(NSString *)fullPath withApplication:(NSString *)appName
    andDeactivate:(BOOL)flag
person jon    schedule 08.02.2011
comment
Я пробовал это, но, похоже, возникла проблема с передачей аргументов, которые имеют пробелы ' ' int, как длинный путь к файлу с пробелами. Я пытался передать в кавычках, но функция возвращает ошибку - person user549164; 08.02.2011
comment
приложение не открывает файл, если в имени файла есть пробелы - person user549164; 09.02.2011