Porting existing LoginItem Logic to the new SMAppService

Hello,

I have many apps that use LoginItem logic to enable the auto start.

I always used the function SMLoginItemSetEnabled to enable or disable the launch of the LoginItem.

I am using macOS Ventura Beta for quite some time now and I noticed that whenever I launch one of my apps, a message appears. It says that my app added some functions. When I click on the message, the Login Items section of the System Preferences opens and my recently opened app is listed under "Allow in the Background".

I want to port my apps to the new logic but I am not quite sure how to do that. I don't want my apps to appear under the "Allow in the Background" section but rather in the "Open at Login" section.

I am using the following code to enable or disable the auto start under macOS 13.0+:

if autoLogin
{
  try? SMAppService.mainApp.unregister()
}
else
{
  try? SMAppService.mainApp.register()
}

This works very well. If I check my switch, the app appears under the "Open at Login" section. If I disable the switch, the app disappears from this list. Great, this is what I want. However...when I restart my Mac, the app is launched automatically. And now there is a new entry in the "Allow in the Background" section again.

What am I doing wrong? Should I register or unregister the LoginItem instead? This is not really what I want, it appears in the wrong section and I think this is confusing for users.

I read somewhere else that the user consent is stored, even when resetting with sfltool or something like that. Does the item appear in this section (and is launched automatically) because I launched the app earlier without my new logic?

Is this simply a bug?

has anyone a working example of how to properly support auto launching an application under macOS Ventura and earlier versions?

Regards, Sascha

Accepted Reply

I want to port my apps to the new logic but I am not quite sure how to do that. I don't want my apps to appear under the "Allow in the Background" section but rather in the "Open at Login" section.

These are very different things:

  • Open at Login shows a list of login items, per the legacy kLSSharedFileListSessionLoginItems API. These items are always launched at login, and are intended to be under the control of the user.

  • Allow in the Background has different semantics. This is an allowlist. It doesn’t show what programs will be launched at login, it shows what programs are allowed to be launched at login [1].

You can see this with the SMLoginItemSetEnabled API:

  1. Enable your Service Management login item by calling SMLoginItemSetEnabled with true.

  2. The item shows up in the Settings list.

  3. Back in your app, disable your login item by calling SMLoginItemSetEnabled with false.

  4. The item still shows up in the list.

Share and Enjoy

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

[1] Assuming we’re talking login items here. It also works for daemons but that’s not your focus.

Replies

I want to port my apps to the new logic but I am not quite sure how to do that. I don't want my apps to appear under the "Allow in the Background" section but rather in the "Open at Login" section.

These are very different things:

  • Open at Login shows a list of login items, per the legacy kLSSharedFileListSessionLoginItems API. These items are always launched at login, and are intended to be under the control of the user.

  • Allow in the Background has different semantics. This is an allowlist. It doesn’t show what programs will be launched at login, it shows what programs are allowed to be launched at login [1].

You can see this with the SMLoginItemSetEnabled API:

  1. Enable your Service Management login item by calling SMLoginItemSetEnabled with true.

  2. The item shows up in the Settings list.

  3. Back in your app, disable your login item by calling SMLoginItemSetEnabled with false.

  4. The item still shows up in the list.

Share and Enjoy

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

[1] Assuming we’re talking login items here. It also works for daemons but that’s not your focus.

So I guess using the main app is wrong then, I still have to use the LoginItem?

try? SMAppService.loginItem(identifier: "com.somecompany.something").register()

Instead of

SMLoginItemSetEnabled( "com.somecompany.something" as CFString, true)

Maybe the description of the Background section could be updated to reflect auto starting apps (via LoginItems).

Edit: Seems to work, I just did not understand it properly. Thanks.

Regards, Sascha

Update:

This is my code now:

try? SMAppService.loginItem(identifier: "com.somecompany.something").unregister() // Successful
SMAppService.loginItem(identifier: "com.somecompany.something").status == .enabled // Returns false, the actual status is 'notRegistered'

However, the app is started automatically after restart. Either there is some sort of remnant of the past on my system...or there is a bug?

Either there is some sort of remnant of the past on my system...or there is a bug?

Well, both are possible (-:

To decide between them, I recommend that you re-test on a ‘clean’ machine. I generally use a VM for this sort of thing, where I can restore the machine to a snapshot between tests. If you don’t have that set up, you can also use a new user account, because login items are scoped per user.

Share and Enjoy

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

Hello,

I completely reset my test machine and now it works as expected. One item was a duplicate of a test version of my app.

I have one additional question: if a user has used my app prior to the release of macOS 13 and set the auto start via SMLoginItemSetEnabled, the item will probably be visible in System Preferences. I would like to remove this Login Item entry and enable the main item entry. Is there any way of doing this? I tried to use SMAppService.unregister, which sets the state properly. However, the item is not removed (like you said, it only shows if the item could make any changes in the background). Can I completely remove the entry (only for my app of course).

Regards

if a user has used my app prior to the release of macOS 13 and set the auto start via SMLoginItemSetEnabled, the item will probably be visible in System Preferences. I would like to remove this Login Item entry and enable the main item entry. Is there any way of doing this?

I don’t have any concrete experience with that scenario, alas.

Share and Enjoy

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