5

I'm working on this app that launches other apps. I'm listening to app launches using:

[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self
 selector:@selector(appLaunched:) name:NSWorkspaceDidLaunchApplicationNotification
 object:nil];

And I launch them using (Mail is just an example):

NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:@"lalalala"], NSWorkspaceLaunchConfigurationArguments, nil];
[[NSWorkspace sharedWorkspace] launchApplicationAtURL:[NSURL URLWithString:@"/Applications/Mail.app"] options:NSWorkspaceLaunchWithoutActivation configuration:dict error:nil];

I did some research, and I saw that you can send an argument when you launch an app (that's why I used the var dict in the code above), but I'm having an issue with this: even using NSWorkspaceLaunchWithoutActivation, the Mail.app is launched and becomes focused with a new composing window. I don't know why it's doing that.

Another thing, if I manage to successfully send a custom argument without focusing the app, how can I check if the app was launched by me (check if the argument is there)?

PS: I'm looking for App Store-ready methods.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Pedro Vieira
  • 3,330
  • 3
  • 41
  • 76
  • 1
    You cannot check another app's launch args unless that app provides an API to do so just like the command line. The argument is the thing you see in main.m of every Cocoa app template. It's I'd standard POSIX argc and argv for main() – uchuugaka Jul 01 '13 at 00:23
  • Can you get a process ID back after launch and use it to query later? – Jasper Blues Jul 01 '13 at 00:30
  • NSWorkspaceLaunchConfigurationArguments is not available for sandboxed apps: https://developer.apple.com/reference/appkit/nsworkspacelaunchconfigurationarguments – Yoav Dec 07 '16 at 19:52

3 Answers3

1

Send the timestamp (UTC) together with the app name you started to your server or a local file if possible.

Then you can track it.

AlexWien
  • 28,470
  • 6
  • 53
  • 83
0

Firstly, I'd try NSWorkspaceLaunchAndHide if NSWorkspaceLaunchWithoutActivation isn't "working". Not ideal, no.. but a kludge...

Secondly... here's a "full, running example" that does the trick..

#import <Cocoa/Cocoa.h>
NSString *psAUX(NSString*grep) {    
    FILE *read_f; char buff[BUFSIZ+1]; int char_rd; NSString *res, *cmnd;
    memset(buff, '\0', sizeof(buff)); 
    cmnd = [NSString stringWithFormat:@"/bin/ps aux|grep -i %@",grep];
    read_f = popen(cmnd.UTF8String, "r");
    if (read_f == NULL) return nil;
    char_rd = fread(buff, sizeof(char), BUFSIZ, read_f);
    if (!char_rd) return nil; 
    return res = [NSString stringWithUTF8String:buff], pclose(read_f), res;
}
int main(int argc, char *argv[]) { @autoreleasepool {         
    NSString* secretStr; NSURL *mailURL; NSDictionary *cfg; NSWorkspace *ws; NSApplication.sharedApplication;
    secretStr = @"TAMPAX";
    mailURL = [NSURL URLWithString:@"file:///Applications/Mail.app"];
    cfg  = @{NSWorkspaceLaunchConfigurationArguments:@[secretStr]};
    ws = NSWorkspace.sharedWorkspace;
    [ws launchApplicationAtURL:mailURL options:0 configuration:cfg error:nil];
    fprintf(stderr,"%s", 

        [psAUX(@"Mail.app") containsString:secretStr] 
      ? "You ARE Mail's baby's daddy!" 
      : "Hands off, she's NOT yours!");

[NSApp run];  }   }

NSLog -> You ARE Mail's baby's daddy!

Congratulations!

Alex Gray
  • 16,007
  • 9
  • 96
  • 118
0

You can create a new Task using NSTask. With NSTask you can set arguments as well as some environment variables to app so that you can check if it is launched by you or by someone else.

Here is the sample code sniffet to do so:

NSTask* taskApp = [[NSTask alloc] init];
[taskApp setLaunchPath:@"App path goes here"];
[taskApp setArguments:[NSArray arrayWithObjects:@"Arg1",@"arg2", nil]];
[taskApp setEnvironment: [[NSProcessInfo processInfo] environment]];
[taskApp launch];
Mahadev Kale
  • 106
  • 10