our app has a helper to perform privileged operations.
previously that helper was installed via SMJobBless() into the /Library/LaunchDaemons/ and /Library/PrivilegedHelperTools/
we also had a script that would install the helper from the command-line, which was essential for enterprise users that could not manually install the helper on all their employee's Macs. the script would copy the files to their install location and would use launchctl bootstrap system as the CLI alternative to SMJobBless(). the full script is here: https://pastebin.com/FkzuAWwV
due to various issues with the old SMJobBless() approach we have ported to helper to the new SMAppService API where the helpers do not need to be installed but remain within the app bundle ( [[SMAppService daemonServiceWithPlistName:HELPER_PLIST_NAME] registerAndReturnError:&err] )
however, we are having trouble writing a (remote-capable) CLI script to bootstrap the new helper for those users that need to install the helper on many Macs at once. running the trivial
sudo launchctl bootstrap system /Applications/MacUpdater.app/Contents/Library/LaunchDaemons/com.corecode.MacUpdaterPrivilegedInstallHelperTool2.plist
would just result in a non-informative:
Bootstrap failed: 5: Input/output error
various other tries with launchctl bootstrap/kickstart/enable yielded nothing promising.
so, whats the command-line way to install a SMAppService based helper daemon? obviously 'installing' means both 'registering' (which we do with registerAndReturnError in the GUI app) and 'approving' (which a GUI user needs to manually do by clicking on the notification or by going into System Settings).
thanks in advance!
p.s. we wanted to submit this as a DTS TSI, but those are no longer available without spending another day on a reduced sample projects. words fail me.
p.p.s. bonus points for a CLI way to give FDA permissions to the app!
Service Management
RSS for tagThe Service Management framework provides facilities to load and unload launched services and read and modify launched dictionaries from within an application.
Posts under Service Management tag
89 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Hi, I'm in the process of creating an App + Helper Tool combo application, and depending on the necessity of root privileges, I'm setting up two paths in the app:
If root privileges are not necessary, I'm using SMJobSubmit rather directly:
var submissionError: Unmanaged<CFError>?
let submissionResult = SMJobSubmit(kSMDomainUserLaunchd, plist, nil, &submissionError)
where plist contains these items:
Label=com.***.redactedApp.redacted,
ProgramArguments=[path/to/helper-tool, commandName, commandArg1, commandArg2]
RunAtLoad=1,
KeepAlive=0
and it works as necessary, and performs the operations.
Now, in the case of privilege escalation being necessary, this call becomes a bit more complex:
let authorization = SFAuthorization()
var authRef: AuthorizationRef?
do {
try authorization?.obtain(withRight: kSMRightModifySystemDaemons,
flags: [.extendRights, .interactionAllowed])
authRef = authorization?.authorizationRef()
} catch let error {
// Logging error
}
var submissionError: Unmanaged<CFError>?
let submissionResult = SMJobSubmit(kSMDomainSystemLaunchd, plist, authRef, &submissionError)
while using the same plist, same executable at the same path, same Label.
However, when using the second path, suddenly SMJobSubmit fails:
Error Domain=CFErrorDomainLaunchd Code=2 "(null)"
Now, naturally I headed over to system logs in Console.app, and this is the weirdest - there is nothing suspicious near the log item I submit with the above error from the main application.
The tool is embedded in the Contents/MacOS folder. However, my problem is that anything that I can think of seems to lead to the same thought: it should be a problem in both cases, not just the privileged one.
Is there something extra that must be taken care of when using SMJobSubmit with privileged helper tools?
I couldn’t create Apple ID account for the past 6 days
I’m developing an app on macOS where I want a daemon/agent to run only when the user explicitly triggers it using SMAppService. The goal is to start the daemon when needed, perform the required task, and then stop/unload it after completion. Additionally, if unload or unregister calls are missed, I want to ensure that the daemon doesn’t start automatically upon reboot. Instead, it should only run when a specific action is taken. What are the best practices and detailed methods for achieving this clean and controlled behavior?
’m developing an app on macOS where I want a daemon/agent to run only when the user explicitly triggers it using SMAppService. The goal is to start the daemon when needed, perform the required task, and then stop/unload it after completion. Additionally, if unload or unregister calls are missed, I want to ensure that the daemon doesn’t start automatically upon reboot. Instead, it should only run when a specific action is taken. What are the best practices and detailed methods for achieving this clean and controlled behavior?
Hi,
we are in the process of exploring how to create an installer for our array of apps.
We have come to the conclusion that regular .pkg installers produced by pkgbuild and productbuild are unfulfilling of our expectations. [1]
Regardless, our installer needs to place files at privileged locations (/Library/Application Support) so we are looking into how to best solve this problem, with the user having
the largest clarity on what they are about to do (so no shady "wants to make changes" dialogs)
the least steps to do to install these files in the right place (so no targeted NSSavePanel-s)
Now, we have done our light reading via some nicely collected posts on the topic (https://forums.developer.apple.com/forums/thread/708765 for example) and the single missing option in the list of privilege escalation models seems to be a one-time privilege escalation from a GUI app.
Our reasons for declaring so:
AuthorizationExecuteWithPrivileges is long deprecated and we are trying to build a futureproof solution
NSAppleScript is just putting up a shady ("wants to make changes") dialog when trying something like this:
$ osascript -e "set filePath to \"/Library/Application Support\"" -e "do shell script \"touch \" & the quoted form of filePath & \"/yyy.txt\" with administrator privileges"
Is there another way to request a one-time authorization from the admin to perform such a simple operation as copying a file to a protected location?
I know it's possible to externalize and internalize Authorization Rights, but they are just an interface to create extra rights and use them as barriers, because they don't actually pass the required right to further operations based on this documentation.
Using SMAppService to register a daemon, which has to be manually allowed by the user adds a lot to the complexity of this installation process, and is something we would like to avoid if possible. (And it's also not the right security model if we want to be honest - we don't want ongoing administrator rights and a daemon)
Is there something we haven't taken into consideration?
[1] preinstall scripts run after the choices are presented during installation and we would need advanced logic (not the limited JavaScript system/files API provided by Installer JS) - plus, the GUI is obviously very limited in a .pkg :(
I have a process [command line cpp application] which i want to run always such as it should relaunch after a crash, after device startup etc.
I created a launchd Property List File with KeepAlive true and placed under /Library/LaunchDaemons.
Problem Statements:
I have a bash script to start and stop this process.
start using: launchctl bootstrap.
stop involve these two steps:
send SIGTERM signal and wait untill process stops after doing some cleanups
launchctl bootout [It doesn't sends SIGTERM]
during steps 1 - Process is getting stop, but also getting immediate relaunch by launchctl
during step 2 - it getting stop again.
is there a proper way so that we can disable KeepAlive temporarily so that process will not launch during step 1?
or suggest other ways to handle this?
I was experimenting with Service Management API and Xcode project from https://developer.apple.com/documentation/servicemanagement/updating-your-app-package-installer-to-use-the-new-service-management-api
and faced some issues with the API.
I replaced agent with XPC service and tried to re-register it.
Use case is a new app package installation with a newer service binary. In order to get the running service restarted with the new binary it's required to unregister old version and register new one. Otherwise the old version would be still running after app upgrade.
The problem is that register fails with "Operation not permitted" error after running unregister which seems to work fine.
Experiments with some delays (500ms) between unregister and register seem to help but it's a not a good solution to work around the problem.
I'm using open func unregister() async throws with description:
The completion handler will be invoked after the running process has been killed if successful or will be invoked whenever an error occurs. After the completion handler has been invoked it is safe to re-register the service.
Sample output with no 500ms sleep between unregister and register calls:
/Library/Application\ Support/YourDeveloperName/SMAppServiceSampleCode.app/Contents/MacOS/SMAppServiceSampleCode unregister && /Library/Application\ Support/YourDeveloperName/SMAppServiceSampleCode.app/Contents/MacOS/SMAppServiceSampleCode register
Successfully unregistered LaunchDaemon(com.xpc.example.service.plist)
Unable to register LaunchDaemon(com.xpc.example.service.plist): Error Domain=SMAppServiceErrorDomain Code=1 "Operation not permitted" UserInfo={NSLocalizedFailureReason=Operation not permitted}
In fact it doesn't seem to be safe to re-register. Any explanation would much appreciated!
=====================================================
Side issue #2: I tried to add a similar helper executable as in the original project with register/unregister and put it inside the same app bundle but at a different location like Contents/Helpers/ folder instead of Contents/MacOS. And it always fails with this error:
Error Domain=SMAppServiceErrorDomain Code=3 "Codesigning failure loading plist: com.okta.service.osquery code: -67028" UserInfo={NSLocalizedFailureReason=Codesigning failure loading plist: com.okta.service.osquery code: -67028}
When I moved the helper binary to Contents/MacOS/ folder along with the main app executable it starts working fine again. Other folders like Resources/XPCServices also don't work.
Is it a hard requirement for an executable to be located inside main Contents/MacOS folder in order to be able to call SMAppService register/unregister APIs? I haven't found any documentation regarding this requirement.
Thanks,
Pavel
When I tried to launch my application from non-gui process (from launch daemon) NSworkspace openApplicationAtURL failed if I tried to run it when my device on the login screen.
Everything is working if someone logged in, but on the login screen I have the error
The application “TestApp” could not be launched because a miscellaneous error occurred. with code 256
NSWorkspace* workspace = [NSWorkspace sharedWorkspace];
NSWorkspaceOpenConfiguration* config = [NSWorkspaceOpenConfiguration configuration];
config.createsNewApplicationInstance = YES;
config.activates = NO;
config.promptsUserIfNeeded = NO;
config.addsToRecentItems = NO;
[workspace openApplicationAtURL: appURL
configuration: config
completionHandler:^(NSRunningApplication *app, NSError *error)
{
}];
Sometimes after the third try it works, sometimes not at all.
I try to use "open" command, it works on MacOS Sequoia, but not working for operating systems below, I see this error
The application cannot be opened for an unexpected reason, error=Error Domain=RBSRequestErrorDomain Code=5 "Launch failed." UserInfo={NSLocalizedFailureReason=Launch failed., NSUnderlyingError=0x600002998120 {Error Domain=OSLaunchdErrorDomain Code=125 "Domain does not support specified action" UserInfo={NSLocalizedFailureReason=Domain does not support specified action}}}
All these problems occur only on the login screen. I'm developing screen share utility, so I need somehow to launch my application on the login screen.
Could someone please help me understand what is recommended way to launch application on the login screen?
I am using [SMAppService registerAndReturnError:] to register a launch agent from a plist bundled in the app (before the registration call a matching unregister is done via unregisterWithCompletionHandler as suggested by the docs). The non standard thing is that I am doing that in a root gui login with sudo to bootstrap my launch agent into gui/0 domain.
This worked well until Sonoma 14.4 - now the call fails with:
Error Domain=SMAppServiceErrorDomain Code=125 "Domain does not support specified action" UserInfo={NSLocalizedFailureReason=Domain does not support specified action}
which is not really helpful.
For now, i've switche to just using launchctl bootout and launchctl bootstrap to get around this, but could anyone elaborate on what has changed? My feeling is that something has changed in the logic that determines the domain - could it be that even with sudo the target domain is gui/ not gui/0 ? As far as I can see there are no ways to specify the domain from the SMAppService APIs right? Also a weird thing is that if run the code in a raw terminal in root gui it works as previously (but out of security, no thing really runs as root, everything is a launch agent under some less privileged user, and before Sonoma 14.4 sudoing with that less privileged user did work for [SMAppService registerAndReturn], now it does not, and what is also strange, doing sudo - and then sudo su also shows the same error code 125.
Context/Project Idea:
I'm currently developing a project that consists of a macOS application using Swift and a local Python backend that executes specific tasks such as processing data. The Python backend is the core of this project, while the Swift application is a mere interface to interact with it.
These two project parts should be decoupled so the user can theoretically run their own backend and connect the Swift application to it. Likewise, the user should be able to connect to the shipped backend using, e.g. curl.
Current plan:
My main idea is to use launchctl to launch a launchd agent which runs the Python backend. The script launching the backend will generate an API key stored in a keychain access group. The Swift application can then get that key and access the backend. The user can always get that API key from the keychain if they want to connect to it programmatically.
Here are the main questions I have currently:
Python Interpreter Consistency: I'm exploring options such as cx_Freeze or PyInstaller to create a standalone Python executable for better system stability. Does anyone have experience with these tools in a macOS environment, or are there other reliable alternatives worth considering?
Adding a Launchd Agent to Xcode: How can I add a launchd agent to my Xcode project to manage a Python executable built with cx_Freeze or PyInstaller? What steps should I follow to ensure it functions properly?
Keychain Access for Launchd Agent: Is it feasible for a launchd agent to access a Keychain access group? What configurations or permissions are necessary to implement this?
Thanks in advance!
I'm working on an enterprise product that's mainly a daemon (with Endpoint Security) without any GUI component. I'm looking into the update process for daemons/agents that was introduced with Ventura (Link), but I have to say that the entire process is just deeply unfun. Really can't stress this enough how unfun.
Anyway...
The product bundle now contains a dedicated Swift executable that calls SMAppService.register for both the daemon and agent.
It registers the app in the system preferences login items menu, but I also get an error.
Error registering daemon: Error Domain=SMAppServiceErrorDomain Code=1 "Operation not permitted" UserInfo={NSLocalizedFailureReason=Operation not permitted}
What could be the reason?
I wouldn't need to activate the items, I just need them to be added to the list, so that I can control them via launchctl.
Which leads me to my next question, how can I control bundled daemons/agents via launchctl? I tried to use launchctl enable and bootstrap, just like I do with daemons under /Library/LaunchDaemons, but all I get is
sudo launchctl enable system/com.identifier.daemon
sudo launchctl bootstrap /Path/to/daemon/launchdplist/inside/bundle/Library/LaunchDaemons/com.blub.plist
Bootstrap failed: 5: Input/output error (not super helpful error message)
I'm really frustrated by the complexity of this process and all of its pitfalls.
btm_launchagent.txt
I have a menu bar app which should be triggered to start when a system extension is successfully installed.
The menu bar app is configured as a agent which should be started by SMAppServer.
SMAppService register/unregister the agent successfully when the program is running locally.
When doing the program installation through JamfNow, which is a MDM system, it fails with following error.
I think the problem here is that the backgroundtaskmanagementd trys to register the agent with an invalid uid=-1 or uid: 4294967295(0xFFFFFFFF).
2024-10-02 10:45:33.100537+0200 0x156d4 Activity 0x1b927 88 0 smd: (BackgroundTaskManagement) BTMManager.getEffectiveDisposition
2024-10-02 10:45:33.103478+0200 0x156dd Default 0x1b927 282 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] effectiveItemDisposition: appURL=file:///Applications/Company%20Agent.app/, type=agent, url=Contents/Library/LaunchAgents/com.Company.agent.notifier.plist -- file:///, config={
BTMConfigArguments = (
);
BTMConfigBundleIdentifiers = (
);
BTMConfigExecutablePath = "Contents/Resources/CompanyNotifier.app/Contents/MacOS/CompanyNotifier";
BTMConfigLabel = "com.Company.agent.notifier";
}
2024-10-02 10:45:33.103544+0200 0x156dd Info 0x1b927 282 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] effectiveItemDisposition: result=[disabled, allowed, visible, not notified]
2024-10-02 10:45:33.105120+0200 0x156d4 Default 0x1b927 88 0 smd: (BackgroundTaskManagement) [com.apple.backgroundtaskmanagement:main] getEffectiveDisposition: disposition=[disabled, allowed, visible, not notified], have LWCR=true
2024-10-02 10:45:33.105181+0200 0x156d4 Default 0x0 88 0 smd: [com.apple.xpc.smd:all] Found status: 0 for <private>
2024-10-02 10:45:33.240190+0200 0x154da Default 0x0 88 0 smd: [com.apple.xpc.smd:SMAppServiceFactory] Setting up BundleProgram keys for <private>
2024-10-02 10:45:33.240250+0200 0x154da Default 0x0 88 0 smd: [com.apple.xpc.smd:SMAppServiceFactory] Setting up BundleProgram keys for <private>
2024-10-02 10:45:33.240388+0200 0x154da Activity 0x1b92a 88 0 smd: (BackgroundTaskManagement) BTMManager.registerLaunchItemWithAuditToken
2024-10-02 10:45:33.243990+0200 0x156dd Default 0x1b92a 282 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] registerLaunchItem: pid=3626, uid=-1, type=agent, parentURL=<private>, url=<private>, config=<private>
2024-10-02 10:45:33.244917+0200 0x156dd Default 0x1b92a 282 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] registerLaunchItem: found existing item: uuid=AC0DBC9B-7A16-443E-ABFC-05DF0F534C08, name=CompanyNotifier, type=managed agent, disposition=[disabled, allowed, visible, notified], identifier=com.Company.agent.notifier, url=Contents/Library/LaunchAgents/com.Company.agent.notifier.plist -- file:///
2024-10-02 10:45:33.245238+0200 0x156dd Debug 0x1b92a 282 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] BTMStore: save scheduled.
2024-10-02 10:45:33.245281+0200 0x156dd Debug 0x1b92a 282 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] RecordSet notification scheduled for uid -1
....
2024-10-02 10:45:33.252358+0200 0x154da Error 0x0 88 0 smd: [com.apple.xpc.smd:SMAppService] Unable to submit job: <private> error: Error Domain=OSLaunchdErrorDomain Code=112 UserInfo={NSLocalizedFailureReason=<private>}
2024-10-02 10:45:33.252707+0200 0x156d4 Default 0x1b92a 88 0 smd: [com.apple.xpc.smd:all] Update request for identifier: <private> uid: 4294967295
2024-10-02 10:45:33.253190+0200 0x156dd Default 0x1b92a 282 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] getItemWithIdentifier: identifier=com.Company.agent.notifier, uid=-1
2024-10-02 10:45:33.253759+0200 0x156d4 Error 0x1b92a 88 0 smd: [com.apple.xpc.smd:btm] Error getting BTMItem with Identifier: <private> uid: 4294967295 error: (null)
2024-10-02 10:45:33.253803+0200 0x156d4 Error 0x1b92a 88 0 smd: [com.apple.xpc.smd:all] Unable to find BTMItem for <private> in 4294967295
2024-10-02 10:45:33.253835+0200 0x156d4 Error 0x1b92a 88 0 smd: [com.apple.xpc.smd:all] Update operation returned error: 3, but no reply expected so error will be silent
2024-10-02 10:45:33.661537+0200 0x156dd Debug 0x0 282 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] sending notification for uid -1, type 131080
2024-10-02 10:45:33.665159+0200 0x154fa Info 0x1b853 282 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] fetchSFLItemsMatching: type=managed user item app
2024-10-02 10:45:33.665374+0200 0x154fa Activity 0x15dd3 282 0 backgroundtaskmanagementd: (BackgroundTaskManagement) BTMManager.userDataDidChange
2024-10-02 10:45:33.666041+0200 0x154da Activity 0x1b92d 88 0 smd: (BackgroundTaskManagement) BTMManager.userDataDidChange
2024-10-02 10:45:33.666651+0200 0x154fa Debug 0x15dd3 282 0 backgroundtaskmanagementd: (BackgroundTaskManagement) [com.apple.backgroundtaskmanagement:main] -[BTMManager handleUserDataDidChangeNotification:]: uid=-1, type=131080
2024-10-02 10:45:33.666085+0200 0x154da Debug 0x1b92d 88 0 smd: (BackgroundTaskManagement) [com.apple.backgroundtaskmanagement:main] -[BTMManager handleUserDataDidChangeNotification:]: uid=-1, type=131080
2024-10-02 10:45:36.218160+0200 0x154fa Debug 0x0 282 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] -[BTMStore handleWriteTimer] entered
2024-10-02 10:45:36.218254+0200 0x154fa Debug 0x0 282 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] -[BTMStore _save] entered
2024-10-02 10:45:36.224738+0200 0x154fa Default 0x0 282 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] BTMStore: store saved to /var/db/com.apple.backgroundtaskmanagement/BackgroundItems-v9.btm
Could it be a problem from the MDM system JamfNow or somewhere else?
The whole logs is as attached.
Thanks!
Hi,
I developed a utility app that allows monitoring system activity and usage. It is a sandboxed app distributed via the Mac App Store. Because in the sandbox I cannot fetch enough data about system activity (like processor temperature, fans, etc.), I developed a little Helper app (non-sandboxed), which currently is distributed via my website, and to enable extra features it provides, the user is asked to download and install it manually (it installs itself as a daemon).
I'm looking for ways to improve the user experience. Ideally, it would be a button inside the main app, which would download and install the helper app, without asking the user to do more than pressing a button.
As far as I understand, in the previous versions of macOS, it would be possible with privileged helpers and SMJobBless, but those are deprecated APIs now.
Another way I tried, is simply downloading the installer app from the website, but opening it programmatically from the main app is tricky since it cannot remove it from the quarantine, in other words, it fails with "operation not permitted".
Any advice is appreciated!
Hi, I'd like to be able to run my daemon process only in pre-logon mode that can be reach by either reboot the machine prior to provide user credentials, or by log out from current user.
So far I couldn't find any useful configuration in the plist file under /Library/LaunchDaemon. Perhaps there's a way to get notification programmatically for when the system enter/exit pre-login mode ?
Thanks
Years ago my daemon was since then using SCDynamicStoreCopyConsoleUser() function and now it longer works.
Basically the daemon needs to know the user name of who is using the system. If I restart the daemon,after the login, it gets the user name.
I tried run a shell command via my daemon ("id -F") and look likes it still picks the root as user name.
So, is there a way to get the current user name using Swift? ProcessInfo.userName fails too
Coming from windows development, I'm trying to understand macOS architecture and how to do certain things. I've already read the Root and Login Sessions AND Service and Daemons AND User Switch Notifications documentation so will frame the questions accordingly.
On Windows, there's a concept of User Sessions, each of which contain One or more WindowStations, each of which contain One or more Desktops. Each user gets at least 3 desktops (e.g. Login/Lock/UAC, Screensaver, and default desktop). From what I understand about macOS, it only has Sessions and then a single Desktop. Is that correct? i.e. same display surface is used to display user's desktop, screensaver, sudo prompt and lock screen?
What about login screen? Does each user get its own login screen process/window running in their session? or is there a common login screen for all users running in one particular session (root?). How does Fast User switching effect login screen?
In a daemon, is it possible to get active console session ID? console meaning the session being displayed on the monitor, whether its login screen, lock screen, user's desktop etc.
In a daemon, is it possible to get session switch notifications? E.g. user logged-in and now their desktop is being displayed, user logged-out and now we're back on login screen, or user switched to another user (Fast User switching). How do I get notification of such events in daemon?
If no user is logged in which session is pre-login agent running in? and after login does the session ID assigned to pre-login agent stay the same and user's session is assigned a new session ID?
Is there always one and only one pre-login agent running?
Is it possible to launch pre-login agent and user agents on-demand with custom commandline arguments from a daemon?
Our team has two products. The first product adds two /Library/LaunchDaemon startup items and one /Library/LaunchAgents startup item, which run normally after installation.
A few months later, our team developed another product, which adds two /Library/LaunchDaemon startup items and one /Library/LaunchAgents startup item. However, we found that on some customers' systems, these startup items for the second product do not load correctly, and the processes do not start. Restarting the system does not resolve the issue. This occurs across systems running versions 14.5 to 14.6.1.
The app's signatures, notarization, and Gatekeeper validations all pass. Eventually, we discovered that by disabling and then re-enabling our team's startup items in the System Settings - Login Items, all the startup items from our team load correctly. Could this be a caching bug related to new startup items from the same team?
When I install my application there is a notification "added items that can run in background". How to I determine why my app is considered for this. What are the configurations / parameters that cause this?
What I did.
Started with the example at https://developer.apple.com/documentation/servicemanagement/updating-your-app-package-installer-to-use-the-new-service-management-api
Changed it to configure a system daemon instead
let service = SMAppService.daemon(plistName: "com.xpc.example.daemon.plist")
Disabled automatic register in the package postinstall script (or else pkg install fails)
Built/Installed the package, it just places files in the disk
Validated install files
Ran the test|register commands by hand
sudo ../SMAppServiceSampleCode.app/Contents/MacOS/SMAppServiceSampleCode" register
Dealt with System Settings user interaction to do this
Validated that com.xpc.example.daemon is installed and ready to work
sudo launchctl list | grep example
sudo launchctl print system/com.xpc.example.daemon
Got it to successfully do some work, YAY sudo ../SMAppServiceSampleCode.app/Contents/MacOS/SMAppServiceSampleCode" test
Expectations
My users would obviously download and install this pkg, so to make it easy for them. I would expect that I could call
SMAppService.daemon(plistName: "...")
.register()
during the package postinstall installation step and the system daemon would be configured.
Observations
After getting all my teeth pulled why can't I just do that?
Why so many hurdles for the dev and the end user, asking them to code sign this and that, notarize this and that, click here and there, accepting this and that?
I understand the job of a developer but for the end user this should be relatively easy.
Questions
Do I need to start a DTS ticket to get this simple flow to work?
It could be I'm missing step 42 in my endeavor :-)