0

Is there a way for a C++ or Objective-C program to tell whether is it being run as a command-line application (e.g. with ./myprog in a shell) or as an app bundle (e.g. by double-clicking on a .app in Finder or running open myprog.app/ in Terminal)?

Currently I'm using the following.

CFBundleRef bundle = CFBundleGetMainBundle();
CFURLRef bundleUrl = CFBundleCopyBundleURL(bundle);
char bundleBuf[PATH_MAX];
CFURLGetFileSystemRepresentation(bundleUrl, TRUE, (UInt8*) bundleBuf, sizeof(bundleBuf));

At this point, bundleBuf now holds the path to the .app bundle or the directory containing the command-line executable. I can check whether the string ends with ".app", but this is hacky. Is there a better way to do this?

Vortico
  • 2,610
  • 2
  • 32
  • 49

1 Answers1

1

You can query the Uniform Type Identifier (UTI) of the URL (using CFURLCopyResourcePropertyForKey() with kCFURLTypeIdentifierKey) and see if it conforms to kUTTypeApplicationBundle (using UTTypeConformsTo()).

CFStringRef uti;
if (CFURLCopyResourcePropertyForKey(bundleUrl, kCFURLTypeIdentifierKey, &uti, NULL) &&
    uti &&
    UTTypeConformsTo(uti, kUTTypeApplicationBundle))
{
    // Is bundled application
}

Using Objective-C, you can use the NSWorkspace methods -typeOfFile:error: and -type:conformsToType: for the same purpose.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • Can you post some example C++ of how to use `CFURLCopyResourcePropertyForKey()`? The documentation doesn't say how to use it, and one of its arguments is a `void*`. – Vortico Oct 14 '19 at 04:42
  • Thanks, this works! For future readers, the header `#include ` is needed for `kUTTypeApplicationBundle`. – Vortico Oct 14 '19 at 08:49
  • `kCFURLTypeIdentifierKey` is now deprecated, and I couldn't get this to work for me, so this may not be viable any more. – Connor Clark Jun 05 '22 at 05:38