SMAppService: How to recover from broken LaunchDaemon registration in Login Items

I was trying out SMAppService on macOS Ventura to register LaunchDaemons and LaunchAgents.

Apparently I didn't get it quite right 🙈 So now I am in a situation where I registered a LaunchDaemons (it showed up in System Settings > General > Login Items) and did not throw an error on registering, but it doesn't really work and I am not able to unregister it.

SMAppService.unregister() returns SMAppServiceErrorDomain Code 113 "Could not find the specified service". The SMAppService instance I am trying to use for unregistering was created the same way that I registered, using SMAppService.daemon(plistName: "some.plist").

Is there any way to reset the state or remove the broken daemon config manually? I tried removing all copies of my app from the system and rebooting, but that didn't clean it out.

I restored to a snapshot now and tried again.

This time, I think I did everything right:

  1. Queried the status of my daemon, got notRegistered (0).
  2. Installed my daemon using SMAppService. Didn't throw, entry appeared in Login Items.
  3. Queried the status again, got requiresApproval (2).
  4. Turned on the daemon in System Settings. Saw it start up and run, producing the expected periodic log messages.
  5. Queried the status again, got enabled (1).
  6. Unregistered the daemon. Saw it terminated and stop logging its periodic messages.
  7. Queried the status again, got notRegistered (0).

However, the entry in System Settings > General > Login Items is not gone. It's still there and enabled. It also persists across reboots & after removing all copies of my app.

So I guess there's still something I missed, or this is simply a bug in the current beta...

I cannot even get that far. if I call

[SMAppService.mainAppService registerAndReturnError:&error]

it returns the error:

Error Domain=SMAppServiceErrorDomain Code=1 "Operation not permitted" UserInfo={NSLocalizedFailureReason=Operation not permitted}

Any idea what the problem could be? Why is it not permitted?

Accepted Answer

Is there any way to reset the state or remove the broken daemon config manually? I tried removing all copies of my app from the system and rebooting, but that didn't clean it out.

In Terminal, run sftool resetbtm, authenticate if needed, and reboot.

However, the entry in System Settings > General > Login Items is not gone. It's still there and enabled. It also persists across reboots & after removing all copies of my app.

That is the current behavior. The state is persisted to preserve user intent.

Repeating comment since it lost formatting:

Error Domain=SMAppServiceErrorDomain Code=1 "Operation not permitted" UserInfo={NSLocalizedFailureReason=Operation not permitted}

Any idea what the problem could be? Why is it not permitted?

You may get this if testing with a plist that is already loaded by launchd (for example, it is installed in /Library/Launch{Agents,Daemons}). 

For debugging, start streaming logs in Terminal: 

sudo log stream --debug --info --predicate "process in { '<my process>', 'smd', 'backgroundtaskmanagementd'} and sender in {'ServiceManagement', 'BackgroundTaskManagement', 'smd', 'backgroundtaskmanagementd'}" 

and repeat your test. If still not clear, file a Feedback with a test project (preferred) or sysdiagnose.

In Terminal, run sftool resetbtm, authenticate if needed, and reboot.

Also trying to reset the state of "Login Items Added by Apps", and I tried this, but said that the command wasn't found. Is that an issue in the first beta, perhaps? 

If it helps, my context is different to the OP – I'm looking to move an login item previously installed using SMLoginItemSetEnabled to SMAppService, and I'd like to test resetting the state of the permission notification.

My comments seem to be disappearing for some reason, so replying:

@Platskies:

Also trying to reset the state of "Login Items Added by Apps", and I tried this, but said that the command wasn't found. Is that an issue in the first beta, perhaps? 

There's a typo in the original reply, it should be sfltool, not sftool.

@Frameworks Engineer

That is the current behavior. The state is persisted to preserve user intent.

Not sure I like the idea of preserving the consent beyond the lifetime of an app on my system. If I delete an app, I typically would like to revoke all consent as well. Also I probably wouldn't want an ever-growing list of apps with login items that were installed on my Mac.

Tried really simple scenario with beta 3

NSError *error = nil;
[SMAppService registerAndReturnError:&error];

Returned error is a generic NSError:

{"Error":"The operation couldn’t be completed. Invalid argument"}

Anyone has any idea?

we are seeing SMAppService.mainAppService.status returning SMAppServiceStatusNotFound for some of our users.

from the documentation:

SMAppServiceStatusNotFound = An error occurred and the framework couldn’t find this service.

however shouldn't it be impossible for the mainAppService to be not found? it seems that return would only make sense for agents/daemons/loginitems. any idea what is going on here?

SMAppService: How to recover from broken LaunchDaemon registration in Login Items
 
 
Q