7

Say you have the name of an application, Mail.app, how do you programmatically obtain com.apple.mail from the application name?

Tony
  • 36,591
  • 10
  • 48
  • 83

5 Answers5

17

The following method will return an application's Bundle Identifier for a named application:

- (NSString *) bundleIdentifierForApplicationName:(NSString *)appName
{
    NSWorkspace * workspace = [NSWorkspace sharedWorkspace];
    NSString * appPath = [workspace fullPathForApplication:appName];
    if (appPath) {
        NSBundle * appBundle = [NSBundle bundleWithPath:appPath];
        return [appBundle bundleIdentifier];
    }
    return nil; 
}

For Mail you can call the method like so:

NSString * appID = [self bundleIdentifierForApplicationName:@"Mail"];

appID now contains com.apple.mail

Swift 5.1

import AppKit

func bundleIdentifier(forAppName appName: String) -> String? {

    let workspace = NSWorkspace.shared
    let appPath = workspace.fullPath(forApplication: appName)
    if let appPath = appPath {
        let appBundle = Bundle(path: appPath)
        return appBundle?.bundleIdentifier
    }
    return nil
}

// For Mail you can call the method like so:

let appID = bundleIdentifier(forAppName: "Mail")

Deprecation

The fullPathForApplication: / fullPath(forApplication:) method has been deprecated in macOS 10.15 - it is unclear what the answer is going forward.

  • Thanks! That's exactly what i was looking for. However, in my tests `Mail.app` works as well, which isn't surprising given that apple says `.app` is optional in many of its docs. However, `MAil.app` and `Mail.APP` also seem to work, so I guess perhaps application name isn't exactly case sensitive either. – Tony Feb 25 '12 at 04:34
  • OK I'll remove the note that says otherwise – David Kennedy of Zenopolis Feb 25 '12 at 09:22
  • Note that `fullPathForApplication:appName` is soft-deprecated in macOS 10.15. I couldn't find any alternative, so I guess Apple wants us to only use bundle identifiers... – Sindre Sorhus Jan 31 '20 at 08:06
  • Thank you Sindre Sorhus, I've added a deprivation notice. – David Kennedy of Zenopolis Feb 11 '20 at 10:18
1

Expanding on Francesco Germinara's answer in Swift 4, macOS 10.13.2:

extension Bundle {
    class func bundleIDFor(appNamed appName: String) -> String? {
        if let appPath = NSWorkspace.shared.fullPath(forApplication: appName) {
            if let itsBundle = Bundle(path: appPath) { // < in my build this condition fails if we're looking for the ID of the app we're running...
                if let itsID = itsBundle.bundleIdentifier {
                    return itsID
                }
            } else {
                //Attempt to get the current running app.
                //This is probably too simplistic a catch for every single possibility
                if let ownID =  Bundle.main.bundleIdentifier {
                    return ownID
                }
            }
        }
        return nil
    }
}

Placing it your Swift project, you can call it like this:

let id = Bundle.bundleIDFor(appNamed: "Mail.app")

or

let id = Bundle.bundleIDFor(appNamed: "Mail")
pkamb
  • 33,281
  • 23
  • 160
  • 191
Todd
  • 1,770
  • 1
  • 17
  • 42
0

You can write:

Swift 5

Import AppKit // Not needed if you already import Cocoa or SwiftUI
    
func bundleIdentifier(forAppName appName: String) -> String? {
    NSWorkspace.shared.runningApplications.first(where:
    { $0.bundleURL?.lastPathComponent == appName })?.bundleIdentifier
}
    
let id = bundleIdentifier(forAppName: "Mail.app")

If you have app names without extension, replace inside the closure with the following code:

$0.bundleURL.localizedName == appName
soundflix
  • 928
  • 9
  • 22
0

It's the value for the key CFBundleIdentifier in Contents/Info.plist

ABS
  • 2,092
  • 1
  • 13
  • 6
  • Adding to that, the application's "Contents" folder can be usually found in /Applications//.app/Contents/ – Ron U Sep 20 '20 at 09:37
-1

This is a possible swift implementation

func bundleIdentifierForApplicationName(appName : String) -> String
{
    var workspace = NSWorkspace.sharedWorkspace()
    var appPath : String = workspace.fullPathForApplication(appName)
    if (appPath != "") {
        var appBundle : NSBundle = NSBundle(path:appPath)
     return appBundle.bundleIdentifier
    }
   return ""
}