MacOsX: Launching an app using NSWorkspace from a

2019-03-31 21:11发布

问题:

I created a Command Line Tool app using Xcode. In that app, I used NSWorkspace to launch another application bundle (.app) as suggested here. MacOsX: How to launch an application (.app) from a "Command Line Tool" type of app

All seem to work fine until I tried to start that Command Line Tool app as a daemon using launchctl. If the daemon is run as the currently logged in user, then the Command Line Tool app launches the external app just fine. If the daemon is run as root, then the Command Line Tool app cannot launch the external app. Using NSWorkspace to open an app doesn't seem to work if the daemon is run as root.

Does anyone know the correct way to open another app from a daemon that's running as root?

回答1:

This is likely a security restriction within MacOS you're running into.

What I would suggest doing is to create a code-signed "helper tool" that resets itself (via setuid -- which I wouldn't do outside of a code-signed app) to the userid of currently logged in user, and then do the NSWorkspace trick to launch the app in that user context.

Creating helper tools is not trivial though. The grand concepts are described in Apple's Authorization Services Programming Guide.

Take a look at Apple's "SMJobBless" sample code, which shows how to install the helper tool that you could set the user rights on and then modify it's helper tool code to launch your app.



回答2:

This is too complicated a subject to really address in a StackOverflow answer. The short answer is that daemons can't launch applications reliably. For the long answer, please read Apple's Technical Note TN2083: Daemons and Agents.



回答3:

I finally got it working by using the code mentioned in this link to get the "console user's" uid and gid: https://superuser.com/questions/180819/how-can-you-find-out-the-currently-logged-in-user-in-the-os-x-gui. The link shows an example of how to use SCDynamicStoreCreate() and SCDynamicStoreCopyConsoleUser() to get "console user's" uid and gid. After getting the uid and gid, just set the uid and gid to those of the console user before using NSWorkspace to open an app and that did the trick for me.