Delite Studio
Five-star iPhone, iPad, Android, and OS X apps
  • Home
  • WordPress
    • Push Notifications for WordPress
      • Documentation
      • FAQs
      • Library for iOS
      • Library for Android
  • Apps
    • Picture Transfer
    • Local Cloud
      • For iOS
      • For Android
    • File Storage
    • File Transfer
      • For iOS
      • For Mac
      • For Android
      • For Windows
    • File Extractor
    • Localizable Strings Merge
    • Delite Blocks
  • About
  • Contact
  • Account
    • Cart
  • English
Select Page ...

Blog

Start dockless apps at login with App Sandbox enabled

October 25, 2011 OS X

The Problem

If we want to run a dockless application at login and we are using Mac OS X 10.5 or later, we can add login items using a shared file list with LaunchServices/LSSharedFileList.h API.

This technique works well until App Sandbox has been introduced. Now, with the file permissions enforcements, accessing the shared file list of login items is forbidden.

This is remarked by Apple here:

“With App Sandbox, you cannot create a login item using functions in the LSSharedFileList.h header file. For example, you cannot use the function LSSharedFileListInsertItemURL.”

The Solution Recommended by Apple

In the “App Sandbox Design Guide”, Apple says:

“Instead, use the SMLoginItemSetEnabled function along with the LSRegisterURL function, as described in “Adding Login Items Using the Service Management Framework” in Daemons and Services Programming Guide.”

Here the details:

“Applications can contain a helper application as a full application bundle, stored inside the main application bundle in the Contents/Library/LoginItems directory. Set either the LSUIElement or LSBackgroundOnly key in the Info.plist file of the helper application’s bundle.

Use the SMLoginItemSetEnabled function (available in Mac OS X v10.6.6 and later) to enable a helper application. It takes two arguments, a CFStringRef containing the bundle identifier of the helper application, and a Boolean specifying the desired state. Pass true to start the helper application immediately and indicate that it should be started every time the user logs in. Pass false to terminate the helper application and indicate that it should no longer be launched when the user logs in. This function returns true if the requested change has taken effect; otherwise, it returns false. This function can be used to manage any number of helper applications.

Note: Before calling the SMLoginItemSetEnabled function, first register with Launch Services by calling the LSRegisterURL function with the URL for the helper application bundle.”

The Helper Application

Why not directly set the application with SMLoginItemSetEnabled? Why do we need to use a helper application?

Because the SMLoginItemSetEnabled function works only with executables stored in the Contents/Library/LoginItems directory of the bundle.

Taking into account this, we can create a minimal (i.e. helper) application with these features:

  1. Standalone, sandboxed and sharing the same bundle.
  2. Stored in Contents/Library/LoginItems.
  3. It must load the main application and then terminate.

The first point can be accomplished creating a new project, enabling App Sandboxing and adding it to the main application project. It's out of topic explain how to do this, there is plenty of tutorials about this argument.

To store the helper app binary in Contents/Library/LoginItems enter the main project info, click on target and go into the Build Phases tab. Here go to the Copy Files detail and set Wrapper as Destination, Contents/Library/LoginItems as Subpath, leave unchecked Copy only when installing and add the Helper Application binary in the list:

Then insert a code like this to load your main application applicationDidFinishLaunching:

[[NSWorkspace sharedWorkspace] launchApplication:
    @"/Path/To/Main/App/Bundle"];

To enable the helper app the main app must:

  1. Register the helper application.
  2. Enable or disable helper application startup loading.

This can be accomplished by the following code:

#import <ServiceManagement/ServiceManagement.h>
+ (void)setStartAtLogin:(NSURL *)bundleURL enabled:(BOOL)enabled {
	// Creating helper app complete URL
	NSURL *url = [bundleURL URLByAppendingPathComponent:
                     @"Contents/Library/LoginItems/MyHelperApp.app"];

	// Registering helper app
	if (LSRegisterURL((CFURLRef)url, true) != noErr) {
		NSLog(@"LSRegisterURL failed!");
	}

	// Setting login
	if (!SMLoginItemSetEnabled((CFStringRef)@"com.mycompany.MyHelperApp",
             enabled)) {
		NSLog(@"SMLoginItemSetEnabled failed!");
	}
}
This only appears to work if your application is in /Applications (not in your Xcode build folder), otherwise you'll get a sandbox violation. And SMLoginItemSetEnabled appears to work even when LSRegisterURL fails.

Some Tips

Setting an application to auto-launch at startup without express consent from the user is forbidden by the Mac App Store Review Guideline #2.26, so if you want to submit your program to the Mac App Store you can:

  • Leave it off by default and make it customizable.
  • Show an alert to get the consent from the user.
Pay attention: violating this rule can take your application to be rejected.
← The iOS Application Life Cycle
How To Internationalize an OS X/iOS App →

5 Responses to Start dockless apps at login with App Sandbox enabled

  • Login items in the sandbox | /dev/random
    1 / 13 / 2012

    […] by the sandbox is adding a login item. A good tutorial on creating login items is available at delite studio, although some changes to the code are needed. That code follows Apple’s earlier guideline of […]

    Login items in the sandbox | /dev/random 1 / 13 / 2012
  • Code Signing issue for Project with Multiple Targets | Ask Programming & Technology
    11 / 7 / 2013

    […] followed the instructions here and here and it works like a charm – the problem is, of course, code signing. I have two targets; the […]

    Code Signing issue for Project with Multiple Targets | Ask Programming & Technology 11 / 7 / 2013
  • Icons | Craig’s Blog
    7 / 6 / 2014

    […] Start dockless apps at login with App Sandbox enabled | Delite Studio has some info. Reading time. Not sure how it works for a menubar app. […]

    Icons | Craig’s Blog 7 / 6 / 2014
  • Return a multidimensional array from pointer duty in Visual C++ - Zweier Gyan
    9 / 12 / 2014

    […] followed a instructions here and here and it works like a attract – a problem is, of course, formula signing. we have twin targets; […]

    Return a multidimensional array from pointer duty in Visual C++ - Zweier Gyan 9 / 12 / 2014
  • blog@timschroeder.net
    11 / 2 / 2014

    […] it is quite tricky to achieve. This tutorial will show how. It is a more comprehensive sequel to Delite Studio’s tutorial from October 2011 and /dev/random’s tutorial from January […]

    blog@timschroeder.net 11 / 2 / 2014
  • Local Cloud for iOS

    Local Cloud for iOS
    iPad / iPhone / Mac / Windows
    Picture Transfer for iOS

    Picture Transfer for iOS
    iPad / iPhone / Mac / Windows
    File Transfer for Mac

    File Transfer for Mac
    Mac
Delite Studio S.r.l. © 2011 - 2019. All Rights Reserved. — P. IVA e Cod. Fisc. IT03402240042 — Privacy Policy
We use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it.OkMore info