Перезапуск приложения cocoa



У меня есть приложение, которое проверяет параметры командной строки и сохраняет значения в постоянных хранилищах. Один из них-пароль, который я не хочу, чтобы люди видели его с " ps " и друзьями. Подход, который я сейчас рассматриваю, заключается в том, чтобы, после того как я сохраню нужные мне значения, перезапустить процесс без параметров командной строки. Мой наивный подход таков, где args[0] - это путь к приложению:

NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:[args objectAtIndex:0]];
[task launch];
[task release];
[NSApp terminate:nil];

Ребенок бежит. Однако, когда мое приложение ребенок не кажется сиротой, но застревает на месте. Я что, совсем сбился с пути?

Дополнительная информация: похоже, что когда я вызываю [nsapp terminate: nil], nstask, который был запущен, застревает, но если я просто выхожу (), то он работает нормально. Однако меня беспокоит то, что вещи, которые открыты (брелок, плист и т. д.) будет в плохом состоянии, если я это сделаю.

И обратите внимание, что во многих примерах кода речь идет о каком-то сторожевом процессе, который при необходимости перезапускает отдельный процесс. Я пытаюсь перезапустить текущий процесс, который уже запущен из этого же процесса.

4   5  

4 ответов:

Есть много примеров в интернете, но Этот (также ниже) выглядит так, как будто у него есть весь код, который вам нужен. Есть и более подробные объяснения.

// gcc -Wall -arch i386 -arch ppc -mmacosx-version-min=10.4 -Os -framework AppKit -o relaunch relaunch.m

#import <AppKit/AppKit.h>

@interface TerminationListener : NSObject
{
    const char *executablePath;
    pid_t parentProcessId;
}

- (void) relaunch;

@end

@implementation TerminationListener

- (id) initWithExecutablePath:(const char *)execPath parentProcessId:(pid_t)ppid
{
    self = [super init];
    if (self != nil) {
        executablePath = execPath;
        parentProcessId = ppid;

        // This adds the input source required by the run loop
        [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(applicationDidTerminate:) name:NSWorkspaceDidTerminateApplicationNotification object:nil];
        if (getppid() == 1) {
            // ppid is launchd (1) => parent terminated already
            [self relaunch];
        }
    }
    return self;
}

- (void) applicationDidTerminate:(NSNotification *)notification
{
    if (parentProcessId == [[[notification userInfo] valueForKey:@"NSApplicationProcessIdentifier"] intValue]) {
        // parent just terminated
        [self relaunch];
    }
}

- (void) relaunch
{
    [[NSWorkspace sharedWorkspace] launchApplication:[NSString stringWithUTF8String:executablePath]];
    exit(0);
}

@end

int main (int argc, const char * argv[])
{
    if (argc != 3) return EXIT_FAILURE;

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    [[[TerminationListener alloc] initWithExecutablePath:argv[1] parentProcessId:atoi(argv[2])] autorelease];
    [[NSApplication sharedApplication] run];

    [pool release];

    return EXIT_SUCCESS;
}

Создайте внешний процесс, который запускает ваш, когда он завершается. Тогда прекратите. Запуск программ Cocoa с помощью NSTask работает не совсем правильно.

Я знаю, что немного поздно отвечать, но этот ответ может помочь другим. Вот классный трюк, который может вам помочь.

С помощью команды terminal просто откройте приложение как новый экземпляр и Завершите текущий экземпляр.

Вот как это делается:

....        
        NSString* path = [[NSBundle mainBundle] bundlePath];

        NSString* cmd = [NSString stringWithFormat:@"open -n %@", path];

        [self runCommand:cmd];

        exit(0);
    }

    /// temrinal function

    -(NSString*)runCommand:(NSString*)commandToRun;
    {
        NSTask *task;
        task = [[NSTask alloc] init];
        [task setLaunchPath: @"/bin/sh"];

        NSArray *arguments = [NSArray arrayWithObjects:
                              @"-c" ,
                              [NSString stringWithFormat:@"%@", commandToRun],
                              nil];
        NSLog(@"run command: %@",commandToRun);
        [task setArguments: arguments];

        NSPipe *pipe;
        pipe = [NSPipe pipe];
        [task setStandardOutput: pipe];

        NSFileHandle *file;
        file = [pipe fileHandleForReading];

        [task launch];

        NSData *data;
        data = [file readDataToEndOfFile];

        NSString *output;
        output = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
        return output;
    }

Для тех, кто все еще хочет использовать NSTask для перезапуска,я нашел один возможный способ: пожалуйста,не устанавливайте NSPipe NSTask,потому что NSTask завершит само приложение,как только приложение завершится, начавшаяся NSTask может застрять там.

По крайней мере,для меня,после того, как я удалил настройки NSPipe, мое приложение успешно перезапустилось. Вот что я делаю:: 1. Напишите инструмент командной строки, который имеет 3 параметра: идентификатор пакета приложений, полный путь приложения, обратите внимание, что в этой командной строке вам нужно завершите приложение и подождите некоторое время,чтобы убедиться, что оно действительно прекращено, прежде чем запускать новое, я продолжаю проверять приложение.isTerminated и сна(1), если это не прекращается.

  1. запустите инструмент командной строки в приложении, используя NSTask, и установите параметры соответственно, не используйте NSPipe, просто создайте NSTask и запустите
  2. приложение перезапускается сейчас

Comments

    No results found.