Перезапуск приложения 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 ответов:
Есть много примеров в интернете, но Этот (также ниже) выглядит так, как будто у него есть весь код, который вам нужен. Есть и более подробные объяснения.
// 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), если это не прекращается.
- запустите инструмент командной строки в приложении, используя NSTask, и установите параметры соответственно, не используйте NSPipe, просто создайте NSTask и запустите
- приложение перезапускается сейчас
Comments