objective-cmacosnstaskworking-directory

Use a relative path with NSTask Arguments in Objective-C


I have virtually no programing experience beyond shell scripting, but I'm in a situation where I need to call a binary with launchd and because of security changes in Catilina, it looks as though it cannot be a AppleScript .app, Automator .app, or a Platypus .app. All three of those call some sort of GUI element and none will work as at startup.

I've cobbled together a snippet of code that compiles and works to call the script I need. I've bundled it a .app, signed it, and it works. But I'd very much like to call the script relative to the binary.

How can I call the equivalent of

[task setArguments:@[ @"../Resources/script" ]];

instead of

[task setArguments:@[ @"/Full/Path/To/script" ]];

Below is the entirety of the main.m

#import <Foundation/Foundation.h>
enter code here
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
       NSTask *task = [[NSTask alloc] init];
        [task setLaunchPath:@"/bin/zsh"];
        [task setArguments:@[ @"/Full/Path/To/script" ]];
        [task launch];
    }
    return 0;
}

As an aside, I know there are much better ways to do this, but my goal os not to have an award winning app, but to simply bridge a specific problem. Many thanks.


Solution

  • You get the current directory with NSFileManager

    NSString* path = [[NSFileManager defaultManager] currentDirectoryPath];
    

    The first argument in argv is the path to the binary

    Either

    NSString *path = [NSString stringWithUTF8String:argv[0]];
    

    or

    NSString *path = [[NSProcessInfo processInfo] arguments][0];