Question

I have an application that spawns subprocesses. These subprocesses require XPCServices, that are in the same application bundle.

My main application has its executable in my.app/Contents/MacOS/my

My XPC service sits in my.app/Contents/XPCServices/com.my.service.xpc

When the subprocess resides in my.app/Contents/Resources/mysubprocess, and the application is being launched, my subprocess can't connect to the XPC service (why not?), but it doesn't show up in the Dock.

If on the other hand the subprocess is in my.app/Contents/MacOS/mysubprocess the subprocess successfully connects to my XPC service (the main application doesn't need anything from this XPC service), the subprocess suddenly gets an own bouncing icon in the Dock. I guess OS X detects if something is being launched from within *.app/Contents/MacOS/* and sees it as application.

I obviously need it to work that way, that the subprocess can connect to the XPC service, but that the subprocess stays hidden and doesn't appear in the Dock. I've tried registering LSUIElement and LSBackgroundOnly at runtime to my user defaults, but that didn't do the trick. If i write LSUIElement into the user defaults, my main application doesn't get a main menu, which is also undesired (but in case of LSUIElement being NO absolutely correct behaviour).

Basically I have two questions: When I move my subprocess binary outside of my.app/Contents/MacOS/ it can't locate the XPCServices. I find that kinda odd, because the relative path to the service stays the same, if the subprocess would be in my.app/Contents/Resources/. I also checked [NSBundle mainBundle] while debugging my subprocess and it had a valid path, even when it was in the Resources folder. Is there a way to somehow tell my subprocess where it should look for my XPC service?

The other approach would be that I can prevent the subprocess of bouncing in the Dock. My main application needs its icon and menu. So is there a way to specify at runtime that the subprocess won't launch a Dock icon, even if it's in the my.app/Contents/MacOS/ folder?

Thank You

Was it helpful?

Solution

According to the Apple Developer docs, XPC services that you as a developer can write must reside in your app’s bundle in My.app/Contents/XPC Services. Your app can only connect to XPC services that reside there and those XPC services can only be connected to from the app whose bundle they reside in.

(Note that the XPC services Apple ships in its system frameworks work a bit differently: /System/Library/PrivateFrameworks/WebKit2.framework contains XPC services that are used by any process that use the WebKit2 framework. But then again, the framework connects to that XPC service, not your app itself.)

That is probably the reason why you can’t connect to the XPC service if your subprocess’ binary is not in My.app/Contents/MacOS/. I’m not sure, but that you can connect to the XPC service from an arbitrary binary that resides in MacOS almost sounds like a bug. But I think it’s not because XPC services only work if the code signature is OK and placing an arbitrary binary in the MacOS directory would break that code signature.

As for the dock icon: How are you spawning the subprocess? Using NSTask? Does the regular app itself use the XPC service? If not, is there any reason why the subprocess isn’t an app itself? That way the XPC service could be inside the subprocess’ /Contents/XPC Services directory and everything should work OK.

Edit: Another solution that comes to mind: Don’t use XPC, but a separate process that talks via Distributed Objects to your subprocesses. Because that doesn’t require any special folder structure or something like that, you can place all auxiliary binaries wherever you want and can therefore avoid the Dock icon bouncing issue.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top