How to find multiple apps with same bundle identifier?
Asked Answered
Q

3

7

Does anyone know of a good way to find (in the filesystem) every app with a given bundle identifier? NSWorkspace and Launch Services let you look for an app by bundle identifier, but only return a single result. I suspect Spotlight (NSMetadataQuery) might help, but I'm a bit unclear on its API, so I'm not sure if there's an appropriate key.

There's the command-line lsregister tool (inside LaunchServices.framework), which can be told to (re)register everything on the system and then dump a report on everything it knows about. Relying on that seems less than ideal, since it's undocumented and parsing its output could be a pain.

(Background: I'm building an app for game modding, and want to provide UI for quickly choosing from a short list of supported games rather than requiring the user to dig through the whole filesystem in an Open panel. However, I expect it's quite likely for a user to have multiple copies of a game installed: release and beta, extra copies for modding, etc.)

Quinnquinol answered 12/1, 2012 at 19:24 Comment(5)
A little more efficiently, lsregister can be told to (re)register just one thing, and then dump a report on everything it knows about.Pauperism
You mentioned Launch Services, but you must have missed seeing LSCopyApplicationURLsForBundleIdentifier() in <LaunchServices/LSInfo.h>. “Launch Services let you look for an app by bundle identifier, but only return a single result”—which function were you referring to? See my answer: https://mcmap.net/q/1442198/-how-to-find-multiple-apps-with-same-bundle-identifierToxicology
@ChrisPage : indeed, back in the 10.7 timeframe I must have missed seeing that Apple would introduce just the function I need three OS X versions later.Quinnquinol
OIC: You asked this in 2012 and it was introduced in OS X 10.10 (2014). Stack Exchange Q&As can have such long lifetimes—rightfully so—and it can be easy to not realize how old a question (or an answer) is. Also, OS X releases have been occurring at an increasing rate than they used to. It would help if people put the OS version in their questions.Toxicology
Still, I'd like to know: Which function were you referring to in your question?Toxicology
T
5

This question was asked in 2012 concerning OS X Lion 10.7. As of OS X Yosemite 10.10 the answer is:

LSCopyApplicationURLsForBundleIdentifier

Summary:

Given a bundle identifier (such as com.apple.finder), find all URLs to the corresponding application.

Discussion:

Returns zero or more URLs to applications that have the specified bundle identifier.

Toxicology answered 11/5, 2016 at 4:31 Comment(2)
How do this in terminal?Lignocellulose
@Lignocellulose I recommend that you ask that in a new Q&A.Toxicology
I
7

You want the kMDItemCFBundleIdentifier Spotlight/metadata key.

pierre$39> mdfind "kMDItemCFBundleIdentifier == 'org.videolan.vlc'"
/Applications/VLC.app
/Applications/vlc-0.8.6c/VLC.app

From there it should just be a matter of making the right calls to the file metadata APIs (pick your poison, Carbon or Cocoa). Interestingly enough, this key is not very well documented: it is not in File Metadata Attributes Reference, though it is in MDItem Reference.

Once again, it goes to show that game modding tools raise use cases few other kind of apps raise, and that sometimes aren't very well served by Apple… </soapbox>

Addendum: once you have your list, in my opinion the best way to present it to the user would be to list the version (kMDItemVersion) of each item you found; you might also show the path, but the version is likely going to be the most useful thing to the user (after all, he likely keeps different instances in order to have specific versions).

Inconvincible answered 8/4, 2012 at 14:52 Comment(9)
This works pretty well, thanks! I am seeing one weird issue, though: when I search for "com.blizzard.WarcraftIII" using mdfind, it works fine, but when I use NSMetadataQuery, the results have a value for kMDItemDisplayName but no kMDItemPath (or kMDItemVersion for that matter). Other bundle IDs work fine (at least those I've tried; my app works with Blizzard games, and WoW and SC2 are the others I have handy for testing). I suspect this is a bug...Quinnquinol
@Quinnquinol You sure you can't get at least the path? (I have War3 but I don't have Xcode on this machine, so I can't check.) Indeed War3 doesn't seem to have a usable version, and even if it's a bug you've got to do something, so if you can get the path or URL (this item has got to be somewhere!), you can apply War3-specific processing to get interesting info, e.g. getting that non-standard BlizzardFileVersion key from Info.plist. BTW, you're a pro for having the reflex to get the display name.Inconvincible
Yup, no path. Clearly NSMetadataQuery found the app and has the path; otherwise it wouldn't have been able to tell me the name... but the result is lacking the kMDItemPath key (and a few others, too). What's more this seems to be the case for any query that finds that app (i.e. searching for it by name won't get a path). Very weird. I'll be doing some looking to see if there are any other app bundles that exhibit this problem and likely asking another question here and/or filing a bug.Quinnquinol
@Quinnquinol OK, Apparently among the oddities of kMDItemPath (it can't be used in a query nor can be used to sort results) is the fact that even though it is not listed in the attributes array, you can nevertheless call valueForAttribute:(NSString*)kMDItemPath and get an answer (make sure to include CoreServices.h and add the CoreServices framework). Put this as a question so that I may give you a proper answer.Inconvincible
Actually, that wasn't (quite) my problem, though I was further thrown off by it. I was testing the values for my keys of interest all at once instead of individually, by throwing them into a dictionary via dictionaryWithObjectsAndKeys:... and since I was putting version in before path, the nil version for War3 terminated the list.Quinnquinol
Ahaa… I tend to iterate and display rather than try and create collections, but that could have caught me too. Objective-C container literals can't come soon enough.Inconvincible
I was using the container for bindings already; otherwise I probably wouldn't have used it for checking values. Yeah, I feel dumb now. Time to go answer some newbie questions so I feel better. :D (And thanks for the literals link... I'd heard about those, er, elsewhere but hadn't seen any details.)Quinnquinol
Note that this will fail if the user happens to have turned off Spotlight.Scarify
As of OS X Yosemite 10.10 the answer is LSCopyApplicationURLsForBundleIdentifier(). See my answer: https://mcmap.net/q/1442198/-how-to-find-multiple-apps-with-same-bundle-identifierToxicology
T
5

This question was asked in 2012 concerning OS X Lion 10.7. As of OS X Yosemite 10.10 the answer is:

LSCopyApplicationURLsForBundleIdentifier

Summary:

Given a bundle identifier (such as com.apple.finder), find all URLs to the corresponding application.

Discussion:

Returns zero or more URLs to applications that have the specified bundle identifier.

Toxicology answered 11/5, 2016 at 4:31 Comment(2)
How do this in terminal?Lignocellulose
@Lignocellulose I recommend that you ask that in a new Q&A.Toxicology
M
1

Another alternative is to use LSCopyApplicationURLsForURL to find all copies of all applications that handle a specific URL scheme. This does require the application to define a URL scheme however.

For example, you could find all email applications that handle the 'mailto' scheme, even if there are multiple versions of the same app on the system.

This is the only way I know to get all applications, instead of what the system considers the 'default' or 'preferred' application returned with other calls.

Marxismleninism answered 19/3, 2014 at 2:12 Comment(2)
True—this works pretty well for cases where the apps you want to find declare unique URL schemes. Not sure that's the case for the apps I was looking for when I asked this a couple of years ago, though. (And welcome to SO!)Quinnquinol
See my answer: LSCopyApplicationURLsForBundleIdentifier https://mcmap.net/q/1442198/-how-to-find-multiple-apps-with-same-bundle-identifierToxicology

© 2022 - 2024 — McMap. All rights reserved.