Service Management

RSS for tag

The 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

71 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

Launch constraints disappear
I use launch constraints in a project. If I archive the project and save a copy of the app locally, everything works as expected but if I choose "Direct Distribution" and submit the app to Apple for notarization, the notarized app does not contain any launch constraints. What are I am doing wrong? Thanks.
4
0
169
36m
Issues with LaunchAgent and LaunchDaemon
I have this application that is divided in 3 parts. A server that handles all the networking code A agent that handles all System related code A manager (NSApplication) to interact with the other two processes. Goals All three process should be kept alive if they crash All three processes must not restart if the user quits them though the NSApplication They need to run during the login window. My current set up using LaunchD is as follows. My Server process plist (relevant part) saved in System/LaunchDaemons key>MachServices</key> <dict> <key>com.myCompany.Agent.xpc</key> <true/> <key>com.myCompany.Manager.xpc</key> <true/> </dict> <key>ProgramArguments</key> <array> <string>PathToExecutable</string> <string>-service</string> </array> <key>RunAtLoad</key> <false/> My agent plist (saved in System/LaunchAgent) <key>QueueDirectories</key> <array> <string>PathToDirectory</string> </array> <key>RunAtLoad</key> <false/> <key>ProgramArguments</key> <array> <string>PathToExecutable</string> <string>service</string> </array> my Manager app plist (saved in System/LaunchAgent) <key>LimitLoadToSessionType</key> <string>Aqua</string> <key>RunAtLoad</key> <false/> <key>ProgramArguments</key> <array> <string>PathToExecutable</string> </array> <key>MachServices</key> <dict> <key>com.myCompany.Agent.manager.xpc</key> <true/> </dict> Currently I have another app that saves a file to the path of the QueueDirectories which triggers the launch of my Agent which then triggers the Server and Manager by starting a XPC Connection. QueueDirectories keeps the Agent alive (and hence all other processes) til file is removed and processes are quited through the manager. XPC Connections Server listens for a connection from agent and manager Manager listens for a connection from agent and starts a connection with server Agent starts a connection with Manager and Server Agent and Manager are owned by the user and server by root The problems When I start Agent by saving a file in the QueueDirectories path and connect to the Server over xpc I end up with two Agents, one owned by the user (the one I expect) and one owned by root. But if I manually start the Agent I do not have that problem. As I mentioned before, the server listens for a connection from the Agent. How do I stop getting two instances? or what is a better way to approach this?
1
0
94
4d
Launch constraints to prevent an agent from being launched manually by a user?
One of our apps contains an agent that is launched at login using a plist in /Library/LaunchAgents. Now the question came up if I can make sure this agent is only launched by the system and cannot be launched by a user or another application. I wonder if this can be done using launch constraints. I played a bit with responsible application constraints but I couldn't make it work. Either the agent didn't launch at all or it could also be launched by just double-clicking on it in Finder. I wonder whether this is even possible. Thanks.
6
0
268
5d
Responsible process launch constraint not working as expected
I wrote a daemon that is launched from the following plist in /Library/LaunchDaemons: <?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>MachServices</key> <dict> <key>com.mycompany.daemon.xpc</key> <true/> </dict> <key>Label</key> <string>com.mycompany.daemon</string> <key>Program</key> <string>/Applications/MyApp.app/Contents/MacOS/MyDaemon</string> <key>AssociatedBundleIdentifiers</key> <string>com.mycompany.myapp</string> <key>SpawnConstraint</key> <dict> <key>team-identifier</key> <string>XXXXXXXXX</string> <key>signing-identifier</key> <string>com.mycompany.myapp</string> </dict> </dict> </plist> No I want to make sure the daemon can only be launched via xpc by MyApp and I embedded the following responsible process plist into the daemon: <?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>team-identifier</key> <string>XXXXXXXXX</string> <key>signing-identifier</key> <string>com.mycompany.myapp</string> </dict> </plist> But as soon as the plist is embedded, macOS refuses to launch the daemon because of a launch constraint violation. As I read in the documentation, the process opening and xpc connection is the responsible process. So what I am doing wrong? Thanks.
3
0
217
2w
Accessing SafariServices from Sandboxed LaunchAgent
I'm attempting to reload a Safari Content Blocker from within a sandboxed command-line tool configured as a LaunchAgent. However, when I use SFContentBlockerManager to reload the content blocker, I encounter the error SFErrorDomain Code=1: Unavailable error. Is it possible to reload a content blocker from a LaunchAgent? If so, how can it be done? // // main.swift // BlockerUpdater // // Created by Sebastian Livoni on 30/06/2024. // import Foundation import SafariServices // Function to reload content blocker asynchronously func reloadContentBlocker() async { NSLog("Hello, World!") do { try await SFContentBlockerManager.reloadContentBlocker(withIdentifier: "me.livoni.blocker.dns") NSLog("Reload complete") } catch { NSLog("Failed to reload content blocker: \(error.localizedDescription)") } } // Main entry point for async code @main struct BlockerUpdater { static func main() async { await reloadContentBlocker() } }
2
0
171
2w
Daemon in an app with a self-update feature
We've got a non-sandboxed app with a built-in daemon that does some root-privileged things for us on occasion. We're using the newest SMAppService APIs, using NSXPCConnections for communications, and generally things work as expected. The daemon is set up to terminate when the parent app terminates. Our app also has (and uses the daemon for) a self-update feature. Once the new app is downloaded, the daemon takes over, replaces the app in-place, terminates the old app and launches the new one. However, after this update, the daemon no longer works. Any other build & launch of the app will silently fail when trying to talk to the daemon. The XPC connection can be constructed as usual, no errors, the process goes along like it should app-side, but the daemon never actually launches and never responds. I can imagine there could be a few rules being broken here with the self-update and the built-in daemon, but what would they be and how can we work within the rules?
12
0
253
1w
Error when trying to check the daemon registration of our application
Hello, Our product registers a daemon in the system through SMAppService (API available from Ventura) and also checks its status in case it has to tell the user to allow the daemon process as a background process. To check the status we call a script written in applescript that returns the status of the service. Script excerpt: NSString* scriptText = @"use framework "AppKit"\n" @"use framework "ServiceManagement"\n" @"use scripting additions\n" @"on startCommand()\n" @"try\n" @"local this, service, SMAppServiceInstance, ret\n" @"set this to a reference to current application\n" @"set SMAppServiceInstance to a reference to SMAppService of this\n" @"set service to SMAppServiceInstance's daemonServiceWithPlistName: "%@"\n" @"set str to service's status as string\n" @"set success to str as number\n" @"return success\n" @"on error errorMessage number errorNumber\n" @"log ("errorMessage: " & errorMessage & ", errorNumber: " & errorNumber)\n" @"end try\n" @"return -1\n" @"end startCommand\n"; The problem we see is sometimes when we try to check the status, a thread that is created when executing the script crashes. This is an error but it doesn't always occur at this point: Crashed Thread: 6 Dispatch queue: com.apple.root.utility-qos.overcommit Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Termination Reason: Namespace SIGNAL, Code 6 Abort trap: 6 Terminating Process: psanwatchdog [61506] Error Formulating Crash Report: PC register does not match crashing frame (0x0 vs 0x7FF89D102A78) Thread 6 Crashed:: Dispatch queue: com.apple.root.utility-qos.overcommit 0 ??? 0x7ff89d102a78 ??? 1 libsystem_kernel.dylib 0x7ff80ce7314a __pthread_kill + 10 2 libsystem_pthread.dylib 0x7ff80ceabebd pthread_kill + 262 3 libsystem_c.dylib 0x7ff80cdd1a39 abort + 126 4 libsystem_c.dylib 0x7ff80cdd0d1c __assert_rtn + 314 5 CoreFoundation 0x7ff80d0e1104 -[__NSPlaceholderDate initWithTimeIntervalSinceReferenceDate:].cold.2 + 35 6 CoreFoundation 0x7ff80cf44cfc -[__NSPlaceholderDate initWithTimeIntervalSinceReferenceDate:] + 370 7 CoreServicesInternal 0x7ff81038da12 BookmarkData::copyItem(CFBookmarkDataItem const*, std::__1::set<CFBookmarkDataItem const*, std::__1::less<CFBookmarkDataItem const*>, std::__1::allocator<CFBookmarkDataItem const*>>&, unsigned long) const + 1780 8 CoreServicesInternal 0x7ff81038df1f BookmarkData::copyDataItemAtOffset(unsigned int, unsigned long) const + 59 9 CoreServicesInternal 0x7ff81036f0dd BookmarkCopyPropertyFromBookmarkData(BookmarkData&, __CFString const*, unsigned long) + 154 10 CoreServicesInternal 0x7ff81036ecc0 _CFURLCreateResourcePropertiesForKeysFromBookmarkData + 242 11 CoreFoundation 0x7ff80cf71893 +[NSURL resourceValuesForKeys:fromBookmarkData:] + 25 12 LaunchServices 0x7ff80d3bf8f9 +[FSNode(BookmarkData) getName:fileIdentifier:creationDate:forBookmarkData:error:] + 205 13 LaunchServices 0x7ff80d3bf0fb _LSAliasCompareToNode + 353 14 LaunchServices 0x7ff80d47e3ce _LSAliasAndInodeOnContainerMatchesNode + 173 15 LaunchServices 0x7ff80d4505d3 _LSBundleMatchesNode(_LSDatabase*, unsigned int, LSBundleData const*, id, unsigned long long) + 97 16 LaunchServices 0x7ff80d3bee21 ___LSBundleFindWithNode_block_invoke + 33 17 LaunchServices 0x7ff80d3bec64 LaunchServices::BindingEvaluation::isBindingOK(LaunchServices::BindingEvaluation::State&, LaunchServices::BindingEvaluation::ExtendedBinding const&) + 165 18 LaunchServices 0x7ff80d3bbf31 LaunchServices::BindingEvaluation::addAndEvaluate(LaunchServices::BindingEvaluation::State&, void ()(LaunchServices::BindingEvaluation::State&), std::__1::vector<LaunchServices::BindingEvaluation::ExtendedBinding, std::__1::allocatorLaunchServices::BindingEvaluation::ExtendedBinding>&) + 4127 19 LaunchServices 0x7ff80d3ba6d3 LaunchServices::BindingEvaluation::runEvaluator(LaunchServices::BindingEvaluation::State&, NSError __autoreleasing*) + 1021 20 LaunchServices 0x7ff80d44bdb4 LaunchServices::BindingEvaluator::getBestBinding(LSContext*, UTTypeRecord* __strong*, NSError* __autoreleasing*) const + 138 21 LaunchServices 0x7ff80d3b9d75 LaunchServices::BindingEvaluator::getBestBinding(LSContext*, NSError* __autoreleasing*) const + 19 22 LaunchServices 0x7ff80d3b94a6 _LSBundleFindWithNode + 586 23 LaunchServices 0x7ff80d3b8a02 _LSFindOrRegisterBundleNode + 228 24 LaunchServices 0x7ff80d58b86a LaunchServices::URLPropertyProvider::capabilityEffectiveNodeForNode(LaunchServices::Database::Context&, FSNode*) + 279 25 LaunchServices 0x7ff80d58a4d7 LaunchServices::URLPropertyProvider::prepareApplicationCapabilityValue(LaunchServices::Database::Context&, id, __FileCache*, __CFString const*, LaunchServices::URLPropertyProvider::State*, NSError* __autoreleasing*) + 226 26 LaunchServices 0x7ff80d3b4e09 LaunchServices::URLPropertyProvider::prepareValues(__CFURL const*, __FileCache*, __CFString const* const*, void const**, long, void const*, __CFError**) + 772 27 CoreServicesInternal 0x7ff81036c057 prepareValuesForBitmap(__CFURL const*, __FileCache*, _FilePropertyBitmap*, __CFError**) + 380 28 CoreServicesInternal 0x7ff8103687cb _FSURLCopyResourcePropertyForKeyInternal(__CFURL const*, __CFString const*, void*, void*, __CFError**, unsigned char) + 266 29 CoreFoundation 0x7ff80cf5c54d CFURLCopyResourcePropertyForKey + 96 30 CoreFoundation 0x7ff80cf5bbca ____CFRunLoopSetOptionsReason_block_invoke_5 + 168 31 libdispatch.dylib 0x7ff80cd09ac6 _dispatch_call_block_and_release + 12 32 libdispatch.dylib 0x7ff80cd0adbc _dispatch_client_callout + 8 33 libdispatch.dylib 0x7ff80cd1a359 _dispatch_root_queue_drain + 1014 34 libdispatch.dylib 0x7ff80cd1a84f _dispatch_worker_thread2 + 152 35 libsystem_pthread.dylib 0x7ff80cea8b43 _pthread_wqthread + 262 36 libsystem_pthread.dylib 0x7ff80cea7acf start_wqthread + 15 The script is executed in the main thread of the application and the process itself does nothing more than launch this script, it is not performing any other tasks apart from recording logs of the script task. Also comment that this error has been seen on Mac machines with rosetta and the compilation of our product is on x86_64 architecture. And to say, if we are using applescript instead of the API it is because the compilation machine uses a Mac Catalina to compile it and we found it convenient to use applescript Any ideas why these errors may occur? Thanks
2
0
165
2w
SMAppService Help!
I'm seeking some help or guidance. I'm attempting to write an app for private use that listens for HID events from a RF reader and responds. I have a functional app, which has to be launched via sudo, to be able to execute IOHIDManagerOpen(manager, IOOptionBits(kIOHIDOptionsTypeSeizeDevice)) correctly. I'm trying to modify this app, now, to use SMAppService and bypass the need for terminal and sudo, but I'm getting confused at what parts of my code need to be embedded into the helper and how to manage communications between the different components. I make it to step 8 in https://developer.apple.com/forums/thread/721737 before I start getting lost. Does anyone know of a functional, SIMPLE, sample app I could take a look at, or a good guide that lays out all parts of an example? Everything I've found gives the bones but no meat.
2
0
217
3w
Privileged daemon appears as unsigned in Login Items
Branching from a previous post titled "Privileged daemon using SMAppService in macOS Sequoia," I have a privileged daemon using SMAppSerice that works in Sonoma and Ventura. In the previous OS versions, privilege is applied in System Settings: Login Items, Allow in the Background. Under macOS sequoia, the daemon appears by its bundle id instead of the parent app, and underneath it reads "Item from unidentified developer" and does not run, even when enabled. I'm wondering if additional steps are needed in the new OS to sign privileged daemons properly?
5
0
272
3w
Privileged daemon using SMAppService in macOS Sequoia
I have some existing code that registers a privileged daemon using SMAppService. In Ventura and Sonoma, the privileged item gets added to Login Items (allow to run in background), and must be toggled on to finish granting privileged access. In 15.0 Beta (24A5264n), the app doesn't show up in the Login Item list. Is there something I should be doing differently to use this framework in Sequoia?
8
0
310
Jun ’24
What does the Legacy Background Tasks toggle do on macOS 15?
On macOS 15 Sequoia, there is a new Legacy Background Tasks toggle in System Settings > Login Items & Extensions. It seems to initially appear (in an "on" state) when an app tries to install a launchd job and places a launch plist in /Library/LaunchDaemons. I have not found any effects of turning this toggle off. I still seem to be able to happily use launchctl bootstrap and launchctl bootout, for example. What does this toggle do? Is there a WWDC session or documentation I haven't found yet?
1
1
326
Jun ’24
Issue with LaunchDaemon running bash showing up as unidentified developer
I have a couple of LaunchDaemon installed helper executables that are calling a bash script. As of MacOS 13, these are now showing up as unidentified developer in Login Items which I am trying to resolve. I have tried setting AssociateBundleIdentifiers in my plist file but the console tells me it is being ignored because bash does not have a Team Identifier. I believe the fully correct way to resolve this is to switch to the new Service Management API, but my understanding is that would only work on MacOS 13 and would therefore break my app on older versions of MacOS My questions are: is there any other way to make my helper as part of my app's login items that I have missed? is there an easy way to make an installer that will work for both newer and older versions of MacOS without having to package two separate versions? Sample plist file: <?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>AssociatedBundleIdentifiers</key> <array> <string>com.mycompany.ExampleApp</string> </array> <key>Label</key> <string>com.mycompany.ExampleApp.updater</string> <key>ProgramArguments</key> <array> <string>/bin/bash</string> <string>/var/root/Library/Group Containers/com.mycompany.ExampleApp/Library/Application Support/update.sh</string> </array> <key>StandardOutPath</key> <string>/var/root/Library/Group Containers/com.mycompany.ExampleApp/Library/update.log</string> <key>WorkingDirectory</key> <string>/var/root/Library/Group Containers/com.mycompany.ExampleApp/Library/Application Support/</string> <key>WatchPaths</key> <array> <string>/var/root/Library/Group Containers/com.mycompany.ExampleApp/Library/Application Support/latest.app.zip</string> </array> </dict> </plist>
1
0
247
May ’24
Restarting my SSH ( forgot my pass )
Emiliss-MacBook-Air ~ % launchctl bootout Usage: launchctl bootout [service-path1, service-path2, ...] | emiliscy@Emiliss-MacBook-Air ~ % sudo launchctl unload /System/Libraly/LaunchDae mons/ssh.plist Unload failed: 5: Input/output error Try running launchctl bootout as root for richer errors. I don't understand what's happening please help me I can't connect github rep with visual studio.
0
0
208
May ’24
How to identify If my executable is launched as User Agent in macOS
I have an executable in macOS that I m launching as a User Agent. The same executable can be launched in multiple ways like either user can directly click the exe to launch it, or user can launch it from the terminal using ./ etc. One similar way is when the user launches the exe as a User Agent(i.e daemon in user session). In this scenarios, I want to identify in my exe If my user has launched it as agent to perform certain task. I wanted to know how can I accurately determine this? I have tried figuring out If there is some unique session that agents operate in, but I could not find anything. Can someone help here? Is this even possible?
1
0
291
May ’24
launching a custom process with launchd is wiping out other application files
I built a custom binary which requires elevated privileges to execute. I wrote a launchd plist file and loaded it. On loading , the app is working as expected but lot of apps were corrupted. Apps like chrome, slack, zoom etc became un openable . Even my mouse right click stopped working. When I looked at the contents of the chrome in application directory it was missing few files. contents of chrome before launching my custom app -rw-r--r--@ 1 myusername admin 2556 May 14 16:49 CodeResources drwxr-xr-x@ 3 myusername admin 96 May 14 15:59 Frameworks -rw-r--r--@ 1 myusername admin 11851 May 14 16:17 Info.plist drwxr-xr-x@ 3 myusername admin 96 May 14 15:59 Library drwxr-xr-x@ 3 myusername admin 96 May 14 16:17 MacOS -rw-r--r--@ 1 myusername admin 8 May 14 15:59 PkgInfo drwxr-xr-x@ 61 myusername admin 1952 May 14 15:59 Resources drwxr-xr-x@ 3 myusername admin 96 May 14 16:17 _CodeSignature -rw-r--r--@ 1 myusername admin 12551 May 14 15:59 embedded.provisionprofile contents of chrome after launching my custom app drwxr-xr-x@ 3 myusername admin 96 May 14 15:59 Frameworks drwxr-xr-x@ 3 myusername admin 96 May 14 15:59 Library drwxr-xr-x@ 2 myusername admin 64 May 16 13:48 MacOS drwxr-xr-x@ 58 myusername admin 1856 May 16 13:48 Resources drwxr-xr-x@ 2 myusername admin 64 May 16 13:48 _CodeSignature my custom app plist file &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.zzzz.xxxx&lt;/string&gt; &lt;key&gt;Program&lt;/key&gt; &lt;string&gt;/path/to/app&lt;/string&gt; &lt;key&gt;RunAtLoad&lt;/key&gt; &lt;true/&gt; &lt;/dict&gt; &lt;/plist&gt; If i run my custom app as a standalone process everything works as expected, no corruption or data loss. To restore the apps, I reinstalled them. But cant figure out why this is happening. Also not sure how to make secondary click work again. I tried with multiple mouses , same issue. Any help on this is appreciated.
1
0
256
May ’24
SMAppService.daemon as root
Hello, I was wondering, is it possible to run SMAppService.daemon... as root? let service = SMAppService.daemon(plistName: "myApp.agent.plist") Also, is it possible to launch the SMAppService.daemon without the XPC connection? The daemon currently supports grpc. I was thinking about running it via Process?
4
0
323
May ’24
Shutdown event in macOS
I wanted to identify the shutdown event in macOS, so that If my application is running and the user performs a system shutdown then my application could be notified of the shutdown event and perform finalization. I came across NSWorkspaceWillPowerOffNotification which is exactly what I require, however, I created a sample application to observe for this notification. Is is observed that right before the system shuts down, the OS terminates my application invoking applicationWillTerminate(_:) delegate and the observer method for 'NSWorkspaceWillPowerOffNotification' is not invoked. I could perform my finalization in the applicationWillTerminate, but I wanted to know why is the observer not getting invoked. Also why is NSWorkspaceWillPowerOffNotification, even provided by apple when it invoked the termination delegate before shutdown? below is how I m adding the observer: NotificationCenter.default.addObserver(forName: NSWorkspace.willPowerOffNotification, object: nil, queue: nil, using: AppDelegate.handlePowerOffNotification) Below is my observer function, which just logs: public static func handlePowerOffNotification(_ notification: Notification) { NSLog (AppDelegate.TAG + "System will power off soon! Perform any necessary cleanup tasks.") // custom logger to log to a file TWLog.Log ("System will power off soon! Perform any necessary cleanup tasks.") }
3
0
506
May ’24