Using private API
I needed a little tool that could show me which app has registered a certain URL on my Mac. Since the ouput of
lsregister -dump is not quite eyecandy I decided to hack together a minimal tool that could do two things:
- show me a list of all registered URLs and their handlers
- be able to unregister a handler
Unfortunately the public API of LaunchServices doesn't help with any of these.
lsregister can unregister apps so it's time to drop it into Hopper and start digging around. Often times this is way easier than you think. Drop lsregister into Hopper and search for unregister. You'll find a symbol
_LSUnregisterURL immediately. If you don't have Hopper available you can use
nm lsregister | grep register.
Helge Heß pointed me to a nice way of making a private function available in Swift. Basically you can load a symbol with
dlsym and then cast it to a type that has C calling convention.
private let handle = dlopen(nil, RTLD_NOW)
private let fnUnregister = dlsym(handle, "_LSUnregisterURL")
typealias fnUnregisterType = @convention(c) (CFURL) -> OSStatus
// now you can cast
let LSUnregisterURL = unsafeBitCast(fnUnregister, to: fnUnregisterType.self)
// and call the function
let result = LSUnregisterURL(url as CFURL)
Actually you cannot run this function out of a sandbox. The obvious choice for such a tool would be to just disable the sandbox but hey: Why not wrap it in an XPCService?