Helper 应用程序无法终止且未启动主应用程序
Helper application cannot be killed and is not launching the main app
关于在登录时启动沙盒应用程序,我还有其他问题,显然没有解决方案:here and here
如您所知,您必须创建一个辅助应用程序来启动主应用程序并终止。
那里的所有教程都说要将其添加到助手委托中:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Get the path for the main app bundle from the helper bundle path.
NSString *basePath = [[NSBundle mainBundle] bundlePath];
NSString *path = [basePath stringByDeletingLastPathComponent];
path = [path stringByDeletingLastPathComponent];
path = [path stringByDeletingLastPathComponent];
path = [path stringByDeletingLastPathComponent];
[[NSWorkspace sharedWorkspace] launchApplication:path];
[[NSApplication sharedApplication] terminate:self];
}
此代码完全没有执行任何操作,因为主应用程序未启动(出于您将在我的其他问题中看到的原因)并且作为奖励,助手未被杀死。
我试过用各种方法杀死帮手,比如
[NSApp terminate:self];
甚至这种戏剧性的方法
NSArray *runningApplications = [[NSWorkspace sharedWorkspace] runningApplications];
NSString *theName;
NSNumber *pid;
for ( NSDictionary *applInfo in runningApplications ) {
if ( (theName = [applInfo objectForKey:@"NSApplicationName"]) ) {
if ( (pid = [applInfo objectForKey:@"NSApplicationProcessIdentifier"]) ) {
//NSLog( @"Process %@ has pid:%@", theName, pid );
if( [theName isEqualToString:@"MyHelper"] ) {
kill( [pid intValue], SIGKILL );
}
}
}
}
没有什么能杀死帮助者。
另一个好处是,当我手动启动主应用程序并且它位于菜单栏上时,我可以选择从主应用程序本身选择 QUIT
,这样我就可以退出应用程序但主应用程序应用程序本身也不可终止,使用相同的编程方法。
这是怎么回事?
我已按照@vadian 的说明进行操作,但它不起作用。 我已将概念验证项目上传到 here。您会看到加载了帮助程序,但没有加载应用程序。
您的方法不完整,无法使用。至少你必须添加这两个路径组件来获取主应用程序的可执行文件的路径(将 MyApp
替换为 MacOS 文件夹中可执行文件的名称)
path = [path stringByAddingPathComponent:@"MacOS"];
path = [path stringByAddingPathComponent:@"MyApp"];
然而,推荐和可靠的方法是检查主应用程序是否已经 运行 并向主应用程序发送 LaunchConfigurationArgument
以指示该应用程序在登录时启动(以及当然要使用 NSBundle
和 NSWorkspace
的现代 URL 相关 API:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
BOOL alreadyRunning = NO, isActive = NO;
NSArray *running = [[NSWorkspace sharedWorkspace] runningApplications];
for (NSRunningApplication *app in running) {
if ([[app bundleIdentifier] isEqualToString:@"com.myCompany.MyApp"]) {
alreadyRunning = YES;
isActive = [app isActive];
break;
}
}
if (!alreadyRunning || !isActive) {
NSURL *bundleURL = [[NSBundle mainBundle] bundleURL];
NSMutableArray *pathComponents = [[bundleURL pathComponents] mutableCopy];
NSUInteger numberOfPathcomponents = [pathComponents count];
[pathComponents removeObjectsInRange:NSMakeRange(numberOfPathcomponents - 3, 3)];
[pathComponents addObject:@"MacOS"];
[pathComponents addObject:@"MyApp"];
NSURL *newURL = [NSURL fileURLWithPathComponents:pathComponents];
NSDictionary *dict = @{NSWorkspaceLaunchConfigurationArguments: @[@"launchedAtLogin"]};
[[NSWorkspace sharedWorkspace] launchApplicationAtURL:newURL
options:NSWorkspaceLaunchWithoutActivation
configuration:dict
error:nil];
}
[NSApp terminate:nil];
}
基本上您不必从其他地方退出助手应用程序。助手应用程序应该在任何情况下自行退出。
关于在登录时启动沙盒应用程序,我还有其他问题,显然没有解决方案:here and here
如您所知,您必须创建一个辅助应用程序来启动主应用程序并终止。
那里的所有教程都说要将其添加到助手委托中:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Get the path for the main app bundle from the helper bundle path.
NSString *basePath = [[NSBundle mainBundle] bundlePath];
NSString *path = [basePath stringByDeletingLastPathComponent];
path = [path stringByDeletingLastPathComponent];
path = [path stringByDeletingLastPathComponent];
path = [path stringByDeletingLastPathComponent];
[[NSWorkspace sharedWorkspace] launchApplication:path];
[[NSApplication sharedApplication] terminate:self];
}
此代码完全没有执行任何操作,因为主应用程序未启动(出于您将在我的其他问题中看到的原因)并且作为奖励,助手未被杀死。
我试过用各种方法杀死帮手,比如
[NSApp terminate:self];
甚至这种戏剧性的方法
NSArray *runningApplications = [[NSWorkspace sharedWorkspace] runningApplications];
NSString *theName;
NSNumber *pid;
for ( NSDictionary *applInfo in runningApplications ) {
if ( (theName = [applInfo objectForKey:@"NSApplicationName"]) ) {
if ( (pid = [applInfo objectForKey:@"NSApplicationProcessIdentifier"]) ) {
//NSLog( @"Process %@ has pid:%@", theName, pid );
if( [theName isEqualToString:@"MyHelper"] ) {
kill( [pid intValue], SIGKILL );
}
}
}
}
没有什么能杀死帮助者。
另一个好处是,当我手动启动主应用程序并且它位于菜单栏上时,我可以选择从主应用程序本身选择 QUIT
,这样我就可以退出应用程序但主应用程序应用程序本身也不可终止,使用相同的编程方法。
这是怎么回事?
我已按照@vadian 的说明进行操作,但它不起作用。 我已将概念验证项目上传到 here。您会看到加载了帮助程序,但没有加载应用程序。
您的方法不完整,无法使用。至少你必须添加这两个路径组件来获取主应用程序的可执行文件的路径(将 MyApp
替换为 MacOS 文件夹中可执行文件的名称)
path = [path stringByAddingPathComponent:@"MacOS"];
path = [path stringByAddingPathComponent:@"MyApp"];
然而,推荐和可靠的方法是检查主应用程序是否已经 运行 并向主应用程序发送 LaunchConfigurationArgument
以指示该应用程序在登录时启动(以及当然要使用 NSBundle
和 NSWorkspace
的现代 URL 相关 API:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
BOOL alreadyRunning = NO, isActive = NO;
NSArray *running = [[NSWorkspace sharedWorkspace] runningApplications];
for (NSRunningApplication *app in running) {
if ([[app bundleIdentifier] isEqualToString:@"com.myCompany.MyApp"]) {
alreadyRunning = YES;
isActive = [app isActive];
break;
}
}
if (!alreadyRunning || !isActive) {
NSURL *bundleURL = [[NSBundle mainBundle] bundleURL];
NSMutableArray *pathComponents = [[bundleURL pathComponents] mutableCopy];
NSUInteger numberOfPathcomponents = [pathComponents count];
[pathComponents removeObjectsInRange:NSMakeRange(numberOfPathcomponents - 3, 3)];
[pathComponents addObject:@"MacOS"];
[pathComponents addObject:@"MyApp"];
NSURL *newURL = [NSURL fileURLWithPathComponents:pathComponents];
NSDictionary *dict = @{NSWorkspaceLaunchConfigurationArguments: @[@"launchedAtLogin"]};
[[NSWorkspace sharedWorkspace] launchApplicationAtURL:newURL
options:NSWorkspaceLaunchWithoutActivation
configuration:dict
error:nil];
}
[NSApp terminate:nil];
}
基本上您不必从其他地方退出助手应用程序。助手应用程序应该在任何情况下自行退出。