How macOS opens a file in the correct app

One of the earliest and most distinctive features of the Mac was its ability to open a file using the right app simply by double-clicking or opening the file. In the days of Classic Mac OS, that was accomplished using the infamous Desktop Database, which recognised files and apps by means of their Creator and Type, two codes consisting of four characters each. A great deal has changed since, for the better. This process now relies on a chain of information to work out which app to launch to open any file. Although that chain can go wrong, in general it’s far more reliable now and seldom needs any user intervention or maintenance.

The chain

When you double-click a file, or use an Open command on it, the file is identified, and checked for any com.apple.LaunchServices.OpenWith extended attribute that sets a custom app association. If that’s present, it tells LaunchServices which app to use to open that specific file. You can set custom associations in the Finder’s Get Info dialog, in the Open With section.

wrongapp00

The com.apple.LaunchServices.OpenWith extended attribute contains a property list specifying:

  • bundleidentifier, e.g. co.eclecticlight.DelightEd
  • path, e.g. /Applications/DelightEd.app
  • version, e.g. 0 to allow any version.

If you use the Get Info dialog to set that back to the default app, that extended attribute may be retained, but then will contain details of the default app instead. You can also manually reset it by deleting the extended attribute, to revert its behaviour to the default.

Most commonly, there’s no such extended attribute, so the default app will be used to open the file. To determine that, LaunchServices gets the type of file, its Uniform Type Indicator or UTI, stored in the file’s attributes. Those are normally set by the filename extension, and mapped to a UTI in a database. For instance, a JPEG image file normally has an extension of JPG or JPEG, case insensitive, which are mapped to the UTI public.jpeg. If a file is being mapped to the wrong type, you can change its extension to one that’s correct for its real UTI, which you can discover using a UTI utility such as my own UTIutility or an equivalent.

Knowing a file’s UTI, LaunchServices then looks up in its database to discover the default editor for that file type. That database is built from information given in the Info.plist property list provided in all app bundles, and the default among those can be set using the Finder’s Get Info dialog, by first setting Open with to your chosen default, then clicking the Change All… button below it.

Now LaunchServices knows the file to open, and the app to open it with, so it sends that app an AppleEvent telling it to open the file. That either opens correctly, or the app may complain that it’s the wrong type or format.

These links in the chain are shown in the diagram below, where your points of control are shown in blue.

openfileInapp

LaunchServices problems

When LaunchServices keeps opening the wrong version or copy of the right app, rather than the one that’s installed in your Dock and your Applications folder, it’s a bit more complicated to fix. It usually helps to discover which copy of the app LaunchServices is opening. Double-click on one of its documents, and Control-click on the app’s icon in the Dock. Towards the bottom of the menu, you’ll see the item Options, in which you can Show in Finder.

wrongapp01

This opens a Finder window on the copy of the app currently used by LaunchServices to open documents with this UTI. That may come as a surprise, as the copy it’s opening may be one you didn’t know about. Rather than removing those unwanted copies of an app until finally LaunchServices opens the right one, there’s a better way to fix that.

Before going any further, check that the version installed in your main Applications folder (or wherever it should be) is the one you want LaunchServices to open, and, if it’s installed there, the app in the Dock is one and the same. Then return to the Finder’s Get Info dialog, and open the list of apps which could open that document in the Open with: item.

wrongapp02

If there are multiple versions of the same app, go to the foot of that menu, and select Other… to bring up an Open File dialog, where you select the copy of the app which you want to open those documents with.

wrongapp03

Click on Open and verify that this is the right copy, via the Dock.

Now that’s set, click on the Change All… button in the Get Info dialog’s Open with: section. You should find LaunchServices opening double-clicked documents using the right app, the right version, and the right copy at last.

Advanced commands

There are two command tools that can be helpful for tackling tougher problems: lsappinfo for getting information from LaunchServices’ database, and lsregister for changing it.

lsappinfo is documented in its man page, which is extensive and fairly accurate, and by usage info in response to the command
lsappinfo -h

The starting point for exploring this command is
lsappinfo list
which is probably best piped into a text file for easy browsing. This lists all running apps and processes known to LaunchServices, and gives a brief summary of what it knows about them. If you want full details on everything running, then pipe
lsappinfo -all list
to a text file, as that tells you pretty well everything LaunchServices knows about apps and processes.

When you’ve got over having so much information in front of you, this tool is most useful for giving information about just one running app or process. To do that, use
lsappinfo -all info "TextEdit"
to show all the information about TextEdit. If you prefer, you can specify the app using its bundle ID:
lsappinfo info "com.adobe.AdobeResourceSynchronizer"

lsregister is buried away in the path /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister Assuming that you’ve aliased it to somewhere readily accessible, the only way to discover its functions is from its usage info
lsregister -h

Useful lsregister commands follow one of two forms:
lsregister [options] [path]
which register and unregister the item (app, usually) specified by the path, and
lsregister [options] [-apps domainlist] [-libs domainlist] [-all domainlist]
which act on the LaunchServices database for the given types (apps, libs, all) and domains. Domains are usually specified as a list of letters:
u,s,l,n
is the complete set, covering user (your Home folder), system, local and network.

In recent versions of macOS, a new option -gc has been added to get LaunchServices to rescan different domains for app info and garbage collect its database. For example,
lsregister -gc -R -v -apps u
checks relevant folders in your Home folder, including ~/Applications, for apps which it needs to add to its database. You can widen this to a full scan of apps using
lsregister -gc -R -v -apps u,s,l

Reset the LaunchServices database using a utility such as OnyX, or
lsregister -kill -r -v -apps u
to affect just the user domain. For more extensive rebuilds, widen its domains, for example with
lsregister -kill -r -v -apps u,s,l
or
lsregister -kill -r -v -all u,s,l
using -seed to scan default locations to seed the new database if you wish.