Service Management

RSS for tag

The Service Management framework provides facilities to load and unload launchd services and read and modify launchd dictionaries from within an application.

Service Management Documentation

Pinned Posts

Posts under Service Management tag

66 Posts
Sort by:
Post not yet marked as solved
21 Replies
4.3k Views
I've got an app that is sandboxed, and it requires a privileged helper. I've worked through the EBAS sample app with various updates to conform with current systems. After a lot of work, I've got to a point where I'm stumped. The Python script SMJobBlessUtil.py returns this error, and I don't know what to do to correct it: <path to helper tool>: tool __TEXT / __info_plist section dump malformed (2) I've gone over the various settings numerous times. It doesn't fail for the EBAS sample, but does for my app. Looking at the binary, the __info_plist sections look identical apart from identifiers. This is what mine looks like (identifiers deleted): <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleIdentifier</key> <string>***</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>***</string> <key>CFBundleVersion</key> <string>1.0</string> <key>SMAuthorizedClients</key> <array> <string>anchor apple generic and identifier "***" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = "***")</string> </array> </dict> </plist> I must be missing something, but I've run out of ideas on where to find it. Anybody got a pointer?
Posted
by Mussau.
Last updated
.
Post not yet marked as solved
3 Replies
420 Views
Hello, we are currently working on a plan to migrate our app suite from Developer ID binaries inside a simple pkg installer to macOS app store distribution. The reason we are using an installer is that there are multiple binaries inside that communicate via XPC and we need to install the respective launchd plist in /Library/LaunchDaemons and /Library/LaunchAgents: 1 root daemon 1 agent that has minimal UI and lives in the system menu bar 1 embedded command line utility in user agent 1 embedded FileProvider extension in user agent 1 embedded Action Extension in user agent 1 agent that only does OAuth stuff Looking through Updating helper executables from earlier versions of macOS I can install the root daemon with SMAppService.daemon(plistName:) and the OAuth helper with SMAppService.agent(plistName:). For the main application I only found SMAppService.mainApp which does not accept a property list configuration. Therefore, I have no place to put my MachServices array and so the File Provider extension, the Action Extension, and the embedded command line utility have no way to talk to the user agent. Currently, XPC is used in between these processes: user agent -> root daemon command line utility -> user agent action extension -> user agent file provider extension -> user agent user agent -> file provider extension: that already works through NSFileProviderServicing I know app-to-app communication only works through launchd for security reasons, but these applications are all part of the same app group (except the root daemon obviously). My question is what is the proper way of starting the user agent so XPC from other binaries just work ™️? Any input is much appreciated!
Posted
by WoamaHons.
Last updated
.
Post not yet marked as solved
0 Replies
345 Views
Because I can't find a way to share StoreKit purchases between two apps (macOS), I was forced to make my LSUIElement application a single app. This is turning out to work reasonably well, except for one issue that I hadn't noticed before (maybe it's new in 14.2?). The normal flow is this: User double-clicks app icon App calls SMAppService.agent(plistName: "com.myagent.plist").register(). The referenced plist points to the same application binary (see attached project) that the user launched in step 1. System launches a second instance of the application binary What I want the call to do instead is see that the app is already running, and just adopt it (that is, if it is killed or crashes, relaunch it). I see two inelegant workarounds: Wait until the user is done configuring the app after first launch, register the app and then quit. Thing is, I can't be sure when they're done, e.g. if they don't close the window. Allow both instances of the app to run, but quit if they close the window and it wasn't launched by launchd, or if there are other instances running. This feels fragile (e.g. if the behavior of register() is ever improved as I'd like). The best solution, of course, would be to share StoreKit context between apps, so I could separate this into the UI app and background agent. (To Apple: I've filed FB13574819 with my project attached.)
Posted
by JetForMe.
Last updated
.
Post not yet marked as solved
4 Replies
440 Views
I have a application that is only the UI for a daemon service. The daemon itself is runnning ok, so far. Now when the user moves the App to trash bin, will the daemon also be uninstalled? How does most MacOS software does that behind the scenes? Like, MS Teams, it runs a daeamon but when the user removes the app the daeamon should be also removed. I am using Packages for installing, so I can for example update, but differently from Windows we normally don`t have an uninstall program. I would appreciate any explanation on that, as for my research I was able to find only how to create daemons.
Posted Last updated
.
Post not yet marked as solved
2 Replies
392 Views
I have an application which uses Service Management framework to register a LaunchAgent. The LaunchAgent registers a mach service with a specific name and it listens for connections made by my application. Also the agent is registered relative to the app bundle using BundleProgram parameter in the agent plist. My problem is that after the initial registration the service always points to the path where my app bundle was located in the time of registration. Here is an example: I download my app from the AppStore and it places it in the /Applications directory. I open it and my service is registered. Then when I want to develop/debug/etc.. from Xcode I build the same app with the same service and I re-register the service from my Debug build and the service still points to the service in the /Applications directory. I tried the use case when I have two builds of my app with a different CFBundleVersion. The LaunchAgent version was the same as the version which made the initial registration, i.e. no matter which app version I use and that I re-register my service, still the initial registered version of the service is used. Based on the documentation in SMAppService.h: If an app updates either the plist or the executable for a LaunchAgent or LaunchDaemon, the SMAppService must be re-registered or it may not launch. It is recommended to also call unregister before re-registering if the executable has been changed. I think that re-registering the application should work in the aforementioned use cases. The only workaround I have found so far is: delete the application which made the initial registration of the service log out log in and open the desired app version and register the service with that version. Does anyone have the same problem and is there a more correct way to handle this use case? Is there a problem in the way I'm using the ServiceManagement framework? Should I write a feedback report to Apple about this problem?
Posted Last updated
.
Post not yet marked as solved
1 Replies
352 Views
I want to start a shell script during the boot of a MacOS (14.2.1) machine. But the scripts is executed only when I log in, not directly after the system has started. I wrote a plist definition like this: > ls -l /Library/LaunchDaemons/com.foobar.justLog.plist -rw-r--r--@ 1 root wheel 397 Jan 25 21:06 /Library/LaunchDaemons/com.foobar.justLog.plist > cat /Library/LaunchDaemons/com.foobar.justLog.plist <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.foobar.justLog</string> <key>RunAtLoad</key> <true/> <key>Program</key> <string>/usr/local/bin/justLog.sh</string> </dict> </plist> > The referenced shell script looks like this: > ls -l /usr/local/bin/justLog.sh -rwxr-xr-x@ 1 root wheel 105 Jan 25 14:46 /usr/local/bin/justLog.sh > cat /usr/local/bin/justLog.sh #!/bin/bash while true ;do echo "Started script $0 as user $(whoami) in $PWD ($(date))" sleep 120 done > Then I shutdown the mac and restarted it at 21:46:40. I waited until 21:48:00 before I logged on with my default user. I was expecting my script to be run after the machine startet. But when I check the files in /var/log/com.apple.xpc.launchd I see that there are no entries from launchd during the initial boot. It looks like launchd does nothing before the first user logs in. That's not the behaviour I would expect from a script to be run when the system boots. > for i in 5 6 7 8 ;do echo "inspecting minute: 21:4$i"; grep "2024-01-25 21:4${i}:" /var/log/com.apple.xpc.launchd/launchd.log{.2,.1,} /var/log/* 2>/dev/null | wc -l ;done inspecting minute: 21:45 11747 inspecting minute: 21:46 0 inspecting minute: 21:47 0 inspecting minute: 21:48 21150 > Can anyone explain why my script is not executed before I log in?
Posted Last updated
.
Post not yet marked as solved
0 Replies
324 Views
If an application has registered Login Items that are running, what happens if the application bundle is replaced with a new version? Does any currently running processes of the login items get relaunched to use the new version? Are there any specific steps required to ensure the new version is used immediately?
Posted Last updated
.
Post marked as solved
2 Replies
448 Views
If the user deletes the app, must something be done to ensure that the launchd agent is removed (or is that something that does not need to be worried about in general)? For more context, I am creating a launchd agent using the SMAppService. I am only an amateur so apologies if this is a bit of a stupid question.
Posted
by teajmin.
Last updated
.
Post not yet marked as solved
1 Replies
420 Views
Platform: MacOS 12.0 I have an app bundle which contains an packet tunnel extension. I am not running my packettunnel extension in a Sandbox as I dont plan to post my app in Apple's App Store. I have an requirement to run privilege operations which I have run any place from the app. As we know the user app cannot run these privilege operations we can use the 'Service Management' api: SMJobBless to start a helper tool which can run these privileged tasks. But as I stated earlier I can run these privileged tasks from any place in the bundle, we have packettunnel extension which is running with root privileges. So looking at my above environment what would be recommended? do I really need to start a privileged helper tool or I can directly run these privileged operations from packettunnel extension? One advantage of running these privilege tasks in packettunnel extension I see is that it will not require additional an user authentication which is needed in case of using SMJobBless(), this will also avoid upgrade management of the helper tool.
Posted
by macnd.
Last updated
.
Post not yet marked as solved
1 Replies
269 Views
Greetings all, I have installed 2 similar function apps (which are safe/signed e.t.c.) I run at different times, and both add items to the Login Items background section, the one is adding a background daemon and is only functioning when the switch is turned to on, while the other adds a PriviledgedHelperTool and can function even if the switch is turned to off, but if it is turned to on, but if I run this app then somehow the other breaks and can not function properly. So as a workaround I keep the PriviledgedHelperTool switch to off and only the other app's daemon switch to on so they can both operate whenever I want. My question has to do with the one that adds the PriviledgeHelperTool, and I wonder if this script contains any crucial information for the functioning of the according application. Though even if I deleted the PriviledgedHelperTool of it from the according folder, and launched the app, it seems it was not regenerated neither any notification shown up or so. Furthermore even if I removed the PriviledgedHelperTool the app seems to function properly, but I would like that thought to be confirmed by some community experts / developers here. I am on MacBook Air M1, macOS Sonoma 14.3 Developer Beta Thank you all in advance for your time. Best regards.
Posted Last updated
.
Post not yet marked as solved
1 Replies
477 Views
Hello I have an App in macOS that is based on two services The first is running as a Daemon The second running as Agent(GUI) I use a script in my app installer (postinstall) that copies the plist files into the folders /Library/LaunchDaemons /Library/LaunchAgents/ And then run for the Daemons: launchctl load And for each user who is currently connected su -c "launchctl load That is working. But when I reboot my machine only the Daemons is running The Agent is not running and in the log "launchctl" There are errors that i can not find any documentation or explanation 2024-01-04 08:01:11.047284 (gui/503 [100004]) &lt;Notice&gt;: Bootstrap by launchctl[1769] for /Library/LaunchAgents/com.sysaid.SessionUtilities.plist succeeded (0: ) 2024-01-04 08:01:11.047289 (gui/503 [100004]) &lt;Notice&gt;: exiting bootstrap mode 2024-01-04 08:01:11.047299 (gui/503/SysAid.Agent [1771]) &lt;Notice&gt;: internal event: SOURCE_ATTACH, code = 0 2024-01-04 08:01:11.048031 (user/503) &lt;Notice&gt;: service inactive: com.apple.xpc.launchd.unmanaged.su.1768 2024-01-04 08:01:11.048039 (user/503) &lt;Notice&gt;: removing inactive unmanaged service: com.apple.xpc.launchd.unmanaged.su.1768 2024-01-04 08:01:11.050192 (gui/503/SysAid.Agent [1771]) &lt;Notice&gt;: Requesting first run LWCR update 2024-01-04 08:01:11.064345 (pid/1759 [AgentCPP]) &lt;Notice&gt;: uncorking exec source upfront 2024-01-04 08:01:11.064352 (pid/1759 [AgentCPP]) &lt;Notice&gt;: created 2024-01-04 08:01:11.085689 (gui/503/SysAid.Agent [1771]) &lt;Error&gt;: Service could not initialize: Unable to verify trusted spawn(/Applications/SysAid Helpdesk.app/Contents/MacOS/AgentSessionUtilities, /Library/LaunchAgents/com.sysaid.SessionUtilities.plist, SysAid.Agent, 3, 503), error 0xa1 - Service cannot be launched because of BTM policy 2024-01-04 08:01:11.085697 (gui/503/SysAid.Agent [1771]) &lt;Error&gt;: initialization failure: 23C71: xpcproxy + 31472 [460][6960F486-3261-3A05-9150-1B1F72E3ADB0]: 0xa1 2024-01-04 08:01:11.085698 (gui/503/SysAid.Agent [1771]) &lt;Error&gt;: Untrusted service was denied launch by BTM. Removing. 2024-01-04 08:01:11.085699 (gui/503/SysAid.Agent [1771]) &lt;Notice&gt;: internal event: INIT, code = 161 2024-01-04 08:01:11.086095 (gui/503/SysAid.Agent [1771]) &lt;Notice&gt;: xpcproxy exited due to exit(78) 2024-01-04 08:01:11.086101 (gui/503/SysAid.Agent [1771]) &lt;Notice&gt;: exited due to exit(78) 2024-01-04 08:01:11.086106 (gui/503/SysAid.Agent [1771]) &lt;Notice&gt;: already handled failed init, ignoring 2024-01-04 08:01:11.086115 (gui/503/SysAid.Agent [1771]) &lt;Notice&gt;: service state: exited 2024-01-04 08:01:11.086123 (gui/503/SysAid.Agent [1771]) &lt;Notice&gt;: internal event: EXITED, code = 0 2024-01-04 08:01:11.086127 (gui/503 [100004]) &lt;Notice&gt;: service inactive: SysAid.Agent 2024-01-04 08:01:11.086131 (gui/503 [100004]) &lt;Notice&gt;: removing service: SysAid.Agent 2024-01-04 08:01:11.086151 (gui/503/SysAid.Agent [1771]) &lt;Notice&gt;: internal event: PETRIFIED, code = 0 2024-01-04 08:01:11.086155 (gui/503/SysAid.Agent [1771]) &lt;Notice&gt;: service state: not running The app and the Installer signed and notarized Can you help me figure out what I'm missing
Posted Last updated
.
Post not yet marked as solved
1 Replies
294 Views
I have a Python script that I've configured to run every 30 minutes. Since it has an associated property list, I've been trying to modify the name that appears in the 'Allow in the Background' section, but I couldn't find an effective way to display the desired name. I tried setting the CFBundleName and CFBundleDisplayName keys in the .plist, but I don't believe they have any impact as they don't seem to change anything. Any other suggested approaches would be greatly appreciated. This is the aforementioned property list: &lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt; &lt;plist version="1.0"&gt; &lt;dict&gt; &lt;key&gt;Label&lt;/key&gt; &lt;string&gt;com.tom.python-cleanup&lt;/string&gt; &lt;key&gt;CFBundleName&lt;/key&gt; &lt;string&gt;Name that i want&lt;/string&gt; &lt;key&gt;CFBundleDisplayName&lt;/key&gt; &lt;string&gt;Name that i want&lt;/string&gt; &lt;key&gt;ProgramArguments&lt;/key&gt; &lt;array&gt; &lt;string&gt;python&lt;/string&gt; &lt;string&gt;/usr/local/tom/cleanup.py&lt;/string&gt; &lt;/array&gt; &lt;key&gt;StandardOutPath&lt;/key&gt; &lt;string&gt;/usr/local/tom/cleanup-service.log&lt;/string&gt; &lt;key&gt;StandardErrorPath&lt;/key&gt; &lt;string&gt;/usr/local/tom/cleanup-service.log&lt;/string&gt; &lt;key&gt;RunAtLoad&lt;/key&gt; &lt;true/&gt; &lt;key&gt;StartCalendarInterval&lt;/key&gt; &lt;dict&gt; &lt;key&gt;Minute&lt;/key&gt; &lt;integer&gt;30&lt;/integer&gt; &lt;/dict&gt; &lt;/dict&gt; &lt;/plist&gt;
Posted
by tcowes.
Last updated
.
Post not yet marked as solved
2 Replies
358 Views
I'm building a Safari content blocker extension. The app is able to use SFContentBlockerManager.reloadContentBlocker to update the content blocker's JSON rules. However, I'm also trying to update the rules in the background through a daemon. The daemon app is embedded inside the main app, and is registered by the main app through SMAppService. The issue I'm running into is I can't get both the GUI app and the daemon to both update the content blocker: If I embed the Safari extension inside the main app and not the daemon, the main app is able to update the extension, but the daemon fails with an "operation couldn’t be completed" error (supposedly because it isn't the owner of the app) Alternatively, if I embed the extension inside the daemon, the main GUI app can no longer update the extension (also failing with "operation couldn't be completed" If I try to embed the extension inside both the main app and the daemon, it works fine when running from Xcode, but App Store Connect verification fails because it won't allow an bundle ID with two periods after the main app ID (e.g. the main app is com.example.App, the daemon is com.example.App.daemon, and the extension is com.example.App.daemon.extension) I'm wondering if I'm missing something here? Is there a way to get Safari to recognize both the main app and the daemon as "owners" of the extension? Thanks in advance!
Posted
by altxg.
Last updated
.
Post not yet marked as solved
0 Replies
283 Views
I work on an app which adds a login item to the user's system. I recently got a report from a user that functionality of the app that talks to the login item wasn't working; upon further investigation, it became apparent that the item was in the requiresApproval state. I plan to update the app to handle this state better, but this situation left me wondering: under what conditions do login items get put into this state immediately upon registration? The documentation mentions "the user needs to take action in System Settings before the service is eligible to run", but doesn't specify when/why this would be the case - I could guess that it's related to macOS accounts with limited privileges or restrictive MDM profiles, but would love to know for certain. Thanks!
Posted
by samsymons.
Last updated
.
Post not yet marked as solved
3 Replies
518 Views
Everything is OK in previous macOS versions. But today when I call try agent.register(). I got an error: - Error Domain=SMAppServiceErrorDomain Code=1 "Operation not permitted" UserInfo={NSLocalizedFailureReason=Operation not permitted} #0 The agent is init with SMAppService.agent(plistName: ...) And I took a look for log: 2023-12-21 01:03:20.398350+0800 0x17e07 Error 0x72960 8028 0 smd: (BackgroundTaskManagement) [com.apple.backgroundtaskmanagement:main] getEffectiveDisposition: error: Error Domain=BTMErrorDomain Code=-95 "record not found" UserInfo={NSLocalizedDescription=record not found} 2023-12-21 01:03:20.398386+0800 0x17e07 Error 0x0 8028 0 smd: [com.apple.xpc.smd:SMAppService] Unable to get disposition of item: <private> error: Error Domain=NSPOSIXErrorDomain Code=3 2023-12-21 01:03:20.398407+0800 0x17e07 Default 0x0 8028 0 smd: [com.apple.xpc.smd:all] Found status: 3 for <private> 2023-12-21 01:03:46.833936+0800 0x17bcc Default 0x72949 8028 0 smd: [com.apple.xpc.smd:SMAppServiceFactory] Setting up BundleProgram keys for <private> 2023-12-21 01:03:46.833986+0800 0x17bcc Default 0x72949 8028 0 smd: [com.apple.xpc.smd:SMAppServiceFactory] Setting up BundleProgram keys for <private> 2023-12-21 01:03:46.836622+0800 0x17e05 Default 0x72949 8029 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] registerLaunchItem: pid=8236, uid=501, type=agent, parentURL=<private>, url=<private>, config=<private> 2023-12-21 01:03:46.839123+0800 0x17e05 Debug 0x72949 8029 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] BTMStore: save scheduled. 2023-12-21 01:03:46.839164+0800 0x17e05 Debug 0x72949 8029 0 backgroundtaskmanagementd: [com.apple.backgroundtaskmanagement:main] RecordSet notification scheduled for uid -2 2023-12-21 01:03:46.903417+0800 0x17bcc Error 0x72949 8028 0 smd: (BackgroundTaskManagement) [com.apple.backgroundtaskmanagement:main] -[BTMManager registerLaunchItemWithAuditToken:type:relativeURL:configuration:uid:]_block_invoke: error: sandbox required 2023-12-21 01:03:46.903449+0800 0x17bcc Error 0x72949 8028 0 smd: [com.apple.xpc.smd:SMAppService] Register of <private> rejected by BTM. Btw, my app is a sandboxed App.
Posted Last updated
.
Post not yet marked as solved
1 Replies
293 Views
I'm working on a macOS application which deals with the system calls, I want one of the calls to be shutdown executable. On click of a button, which is available in the application, the system should get shutdown. I'm able to achieve this, but everytime it is invoked, user is prompted with the sudo permission, which I want to avoid. There should not be any user intervention and the system must be shutdown. No applescript please. The user should never be prompted with the sudo permission grant and the code can be objc or swift.
Posted
by himanshus.
Last updated
.
Post not yet marked as solved
1 Replies
359 Views
Recently, I encountered a weird bug that I could not have a clue about. I have an API to save the configuration settings to a plastic, which is located at "/Library/Preferencs/Bitglass". The writer is a daemon and the function looks as follows. The weird thing I found recently was that the function could not save the IPC server port value when the daemon was installed by another installer daemon. But it can save other plastic values without any problems. When the list was not saved to a file, there is not any error messages. The following function is called by two daemons to save different settings into a plastic file. Is there anyone who has any clue why it failed to save the plist to a file when the daemon is installed and launched by another daemon? (BOOL)setValue:(const char *)key value:(const char *)value { std::lock_guardstd::mutex lock(plist_mutex); NSString *nskey = [NSString stringWithUTF8String:key]; NSString *nsval = [NSString stringWithUTF8String:value]; @try { [data setObject:nsval forKey:nskey]; if (![data writeToFile:plistPath atomically:YES]) { BGLOG(LOG_ERROR, "Failed to write" &lt;&lt; key &lt;&lt; "=" &lt;&lt; value); return FALSE; } return TRUE; } @catch (NSException *e) { BGLOG(LOG_ERROR, "Caught exception:" &lt;&lt; [e.name UTF8String] &lt;&lt; " reason:" &lt;&lt; [e.reason UTF8String]); return FALSE; }
Posted
by Andy2023.
Last updated
.
Post not yet marked as solved
7 Replies
643 Views
Apple M2 Pro MacOs: 13.6 (22G120) In my system extension installer's postInstall script I have launch agent configured for the app as below: launchctl enable gui/$user_uid/com.mycompany.client.myproduct launchctl bootstrap gui/501 /Library/LaunchAgents/com.mycompany.myproduct.plist When I install the software using a local user, the service works fine without any issue and the service is shown listed in 'launchctl list' command: % launchctl list | grep -i mycompany 84714 0 com.mycompany.client.myproduct But when I login using on the same machine using a AD (Active Directory) user, the service/agent doesnt start and I don't see any entry service listed in 'launchctl list'. This is how my plist file looks like: % defaults read /Library/LaunchAgents/com.mycompany.myproduct.plist { CFBundleVersion = "200.200.200.200"; KeepAlive = 1; Label = "com.mycompany.client.myproduct"; LimitLoadToSessionType = ( Aqua ); ProgramArguments = ( "/Applications/mycompany.app/Contents/MacOS/Mycompany Module" ); RunAtLoad = 1; Version = "200.200.200.200"; } What am I missing here?
Posted
by macnd.
Last updated
.
Post not yet marked as solved
1 Replies
328 Views
I'm getting this message in a launchd log. The service in question is a Focusrite thing. What does it mean? (system/com.focusrite.ControlServer) : cannot spawn: service is in penalty box The peripheral seems to be working fine.
Posted
by hacksaw.
Last updated
.