Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

Cleanup LaunchAgents after development

I have been playing with application bundled LaunchAgents:

  • I downloaded Apple sample code,
  • Run the sample code as is,
  • Tweaked the sample code a lot and changed the LaunchAgents IDs and Mach ports IDs,
  • Created new projects with the learnings, etc.

After deleting all the Xcode projects and related project products and rebooting my machine several times, I noticed the LaunchAgent are still hanging around in launchctl. If I write launchctl print-disabled gui/$UID (or user/$UID) I can see all my testing service-ids:

disabled services = {
  "com.xpc.example.agent" => disabled
  "io.dehesa.apple.app.agent" => disabled
  "io.dehesa.sample.app.agent" => disabled
  "io.dehesa.example.agent" => disabled
  "io.dehesa.swift.xpc.updater" => disabled
  "io.dehesa.swift.agent" => disabled
}

(there are more service-ids in that list, but I removed them for brevity purposes).

I can enable or disable them with launchctl enable/disable service-target, but I cannot really do anything else because their app bundle and therefore PLIST definition are not there anymore. How can I completely remove them from my system?

More worryingly, I noticed that if I try to create new projects with bundled LaunchAgents and try to reuse one of those service-ids, then the LaunchAgent will refuse to run (when it was running ok previously). The calls to SMAppService APIs such .agent(plistName:) and register() would work, though.

Answered by DTS Engineer in 838464022

There’s a fundamental issue in play here: macOS doesn’t know whether an app has really been deleted. This results in a number of odd behaviours that regularly get noted here on the forums. You’ll find a good example here.

The calls to SMAppService APIs such .agent(plistName:) and register() would work

I’d like to clarify this:

  • Does “work” mean that they let you ‘resurrect’ these disabled jobs?

  • Or does it mean that the API calls work but don’t successfully get the jobs working again?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

There’s a fundamental issue in play here: macOS doesn’t know whether an app has really been deleted. This results in a number of odd behaviours that regularly get noted here on the forums. You’ll find a good example here.

The calls to SMAppService APIs such .agent(plistName:) and register() would work

I’d like to clarify this:

  • Does “work” mean that they let you ‘resurrect’ these disabled jobs?

  • Or does it mean that the API calls work but don’t successfully get the jobs working again?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

After deleting all the Xcode projects and related project products and rebooting my machine several times, I noticed the LaunchAgent are still hanging around in launchctl. If I write launchctl print-disabled gui/$UID (or user/$UID) I can see all my testing service-ids

Basically, I would love to know the way to clean up after "myself" once an app is being uninstalled or has been uninstalled. I understand the OS cannot know if an app has been truly uninstalled (due to the issues described in your link); however, I would like to "liberate" those IDs (both launchAgent id and mach port ID). I have been reading launchctl man pages and searching on the internet and I am unable to figure out how to clean up that state.

The goal is not to clean up for clean up sake, but not being able to execute bundle LaunchAgents due to some weird error in launchctl which has no way to be fix is quite worrysome.

I see two points here:

  • How things should work (A).

  • Getting your product working (B).

I’m not really in a position to tackle the first. If you have strong opinions about what macOS should or shouldn’t support, I encourage you to file an enhancement request with the details. And if you do that, please post your bug number, just for the record.

As terms of getting a product working today, you wrote:

The latter. SMAppService.agent(plistName:) returns a SMAppService instance. I can successfully call register on it (i.e. no error is thrown). However, the bundled LaunchAgent is not launched or the connection (I'm using the Swift API) cannot be established.

Well, that doesn’t sound good. Are you able to reproduce that on a ‘clean’ machine? So, something like:

  1. Install a test project on a Mac that’s never seen it before.

  2. Set up your agent.

  3. Remove your app like a user might, for example, by dragging it to the trash. Or by, say, running an uninstall feature in your app.

  4. Install a new version.

  5. Try to set up your agent and have it fail as you’ve described.

Note I usually do this sort of testing on a VM, so I can restore from a fresh snapshot between each test.

If so, I’d love to hear those details.

For context, I’m reluctant to go chasing bugs that only show up on developer machines. Such machines tend to get into weird states because you’re continuously building and rebuilding your product. And while it’s reasonable to ask for ways to get out of those states — see my response point A above — I prefer to focus on things that affect real users.

ps It’s better to reply as a reply, rather than in the comments; see Quinn’s Top Ten DevForums Tips for this and other titbits.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Cleanup LaunchAgents after development
 
 
Q