Search code examples
macoscocoaappkitnsworkspace

-[NSWorkspace openApplicationAtURL:configuration:completionHandler:] does not work in login item


In my MacOS app there is a login item that uses -[NSWorkspace launchApplicationAtURL:options:configuration:error:] method to launch the main app. It works fine but this method is deprecated now in favour of -[NSWorkspace openApplicationAtURL:configuration:completionHandler:]. When I try to use the latter, nothing happens. No app is getting launched and no errors are getting reported. Here is the original code with small details omitted.

int main() {
  @autoreleasepool {
    NSBundle* bundle = NSBundle.mainBundle;
    NSWorkspace* workspace = NSWorkspace.sharedWorkspace;

    NSString* path = bundle.bundlePath;
    for (int i = 0; i < 4; ++i) {
      path = [path stringByDeletingLastPathComponent];
    }

    NSDictionary* env = @{
//      ...
    };
    
#if 1 /* switch between new and old method versions */
    NSWorkspaceOpenConfiguration* configuration = [NSWorkspaceOpenConfiguration new];
    [configuration setEnvironment: env];
    [configuration setPromptsUserIfNeeded: YES];
    [workspace openApplicationAtURL: [NSURL fileURLWithPath: path] configuration: configuration completionHandler:^(NSRunningApplication* app, NSError* error) {
      if (error) {
        NSLog(@"Failed to run the app: %@", error.localizedDescription);
      }
    }];
#else
    NSDictionary* configuration = @{ NSWorkspaceLaunchConfigurationEnvironment: env };

    NSError* error = nil;
    [workspace launchApplicationAtURL: [NSURL fileURLWithPath: path]
                              options: NSWorkspaceLaunchDefault
                        configuration: configuration
                                error: &error];

    if (error) {
      NSLog(@"Failed to run the app: %@", error.localizedDescription);
    }
#endif
  }
  return 0;
}

Does anyone have a similar issue? What am I doing wrong with the new method?


Solution

  • Figured it out. The login item quits too soon. It should wait for the open operation to be completed. Something like:

        [workspace openApplicationAtURL: [NSURL fileURLWithPath: path] configuration: configuration completionHandler:^(NSRunningApplication* app, NSError* error) {
          if (error) {
            NSLog(@"Failed to run the app: %@", error.localizedDescription);
          }
          exit(0);
        }];
        [NSThread sleepForTimeInterval: 10];