Page 1 of 1
Forum

Welcome to the Tweaking4All community forums!
When participating, please keep the Forum Rules in mind!

Topics for particular software or systems: Start your topic link with the name of the application or system.
For example “MacOS X – Your question“, or “MS Word – Your Tip or Trick“.

Please note that switching to another language when reading a post will not bring you to the same post, in Dutch, as there is no translation for that post!



Share:
Notifications
Clear all

[Solved] Lazarus Pascal - macOS - Use SMAppService to add a login item (macOS 13+)

1 Posts
1 Users
0 Reactions
364 Views
 Hans
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 2869
Topic starter  

As of macOS 13, Apple introduced SMAppService as a replacement for SMLoginItemSetEnabled.
Figuring out how this works was very confusing with the contradicting information I ran into - probably due to the difference between starting an application and starting a service or daemon.

Anywho, long story short, it took me a ton of work to finally figure it out. Special thanks to The Eskimo in the Apple Developer forum who quick and concise showed me how to use SMAppService properly. Without his help I'd still be bumbling around trying to figure it out.

So what I want to do: Have the ability to add my application, distributed through the App Store, to the Login Items.

For this I'll use SMAppService by calling 3 basic functions:

  • registerAndReturnError - Register/add login item
  • unRegisterAndReturnError - unregister/remove login item
  • status - is my app already a login item or not?

These 3 functions can be called within your application, and there is no need to create a helper tool for this.
We do however need a link to the headers of macOS 13 (or newer) since Lazarus is still shipping with links to the macOS 10.10 SDK (if I'm recalling that correctly). Took me a lot of time and effort, but I got it to work (Lazarus /FPC can be quite the miracle if you as ask me(.

I created this unit, ServiceManagementAppService.pas (feel free to name it something else), basically only looking at the 3 functions I need for now:

unit ServiceManagementAppService;

{$mode objfpc}{$H+}
{$modeswitch objectivec1}
{$linkframework ServiceManagement}

interface

uses Classes, SysUtils, CocoaAll;

const
  SMAppServiceStatusNotRegistered	=0;
  SMAppServiceStatusEnabled		=1; 
  SMAppServiceStatusRequiresApproval	=2; 
  SMAppServiceStatusNotFound		=3;

  SmAppServiceStatusResult :
    Array [0..3] of string = 
                            ('Not registered',
                             'Enabled',
                             'Requires Approval',
                             'Not found' );  
type
  SMAppServiceStatus = NSInteger;
  
type
  SMAppService = objcclass external (NSObject)
  public
    function  registerAndReturnError(error: NSErrorPtr): objcbool;  message 'registerAndReturnError:';
    function  unregisterAndReturnError(error: NSErrorPtr): objcbool;  message 'unregisterAndReturnError:';
    function  status:SMAppServiceStatus; message 'status';
  end;

implementation

end.

 

Now include this unit in your application's uses clause of course and you can call register, unregister and status as showns in these example calls:

var
  appService: SMAppService;
  StatusReturn : SMAppServiceStatus;
  Registered:boolean;
  UnRegistered:boolean;
begin
  try
    // Create a service
    appService := SMAppService.new;

    // Resgister service
    Registered := appService.registerAndReturnError(nil);

    // Unregister service
    UnRegistered := appService.unregisterAndReturnError(nil);

    // Get current status
    // StatusReturn:
    // SMAppServiceStatusNotFound      - your app was never registered as login item
    // SMAppServiceStatusEnabled       - your app is registered as a login item
    // SMAppServiceStatusNotRegistered - your app is registered as a login item
    
    StatusReturn := appService.status;
    
  except
    Showmessage('fail');
  end;
end; 

Caution: as I understand, per Apple guidelines, your app is not allowed to just add itself to the Login items without user interaction. So handle this call with care,

 

Note: Not sure if it is required, but I did compile with the '-WM13.0' compiler (Lazarus -> Project -> Options -> Compiler Options -> Custom Options) - not sure if this is a requirement.


   
ReplyQuote
Share: