Search code examples
macoscocoalaunchdlaunch-agent

cocoa - how to make a non-sandbox macOS app start at login?


I am developing a non-sandbox macOS app which is not going to be released in App Store, and I want to make the app to run when user log in.

The current method I have found is to use Service Management framework and a helper app, which needs to sign this app. The former valid way was LSSharedFileList, but this method doesn't work in macOS 10.14.

Is there a way I can make this simple app start at login?


Solution

  • You can register any app with launched to run as a user agent.

    In this example, an app named On Startup will be launched whenever the user logs in.

    Step 1

    You'll need to create a "launchd.plist" file to describe the service. In this example, you create a file named com.yourdomain.onstartup.plist with the following content:

    <?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>Label</key>
        <string>com.yourdomain.onstartup</string>
        <key>LimitLoadToSessionType</key>
        <string>Aqua</string>
        <key>Program</key>
        <string>/Applications/On Startup.app/Contents/MacOS/On Startup</string>
        <key>RunAtLoad</key>
        <true/>
    </dict>
    </plist>
    

    The key point is the RunAtLoad property that tells launchd to start the process when the user session loads.

    (Note: you can create this file by building a dictionary and writing it as a property list.)

    Step 2:

    Install that file in ~/Library/LaunchAgents. This is where launchd looks for per-user launchd configuration files.

    Step 3:

    Execute the command

    launchctl bootstrap ~/Library/LaunchAgents/com.yourdomain.onstartup.plist
    

    or simply wait until the system restarts.

    The bootstrap command tells launchd that a new service wants to be registered and activated immediately, but all of the files in LaunchAgents will get registered automatically the next time the user logs in.

    If you need your app to run all the time, consider adding a KeepAlive property. And there are about a billion other options.

    Step 4:

    To stop your app from starting again at login, delete the com.yourdomain.onstartup.plist file.

    If you've set the KeepAlive property, you'll also want to invoke launchctl bootout gui/501/com.yourdomain.onstartup command to stop the service and unregister it immediately. (Note: this will kill your app.)

    See

    man launchd.plist

    man launchctl

    macOS Daemons and Services