How can I automatically run the program at login?

How to configure the menu bar application to start automatically at login? I want this to be the default. Can I do this by simply adding bool to info.plist?

+9
source share
3 answers

(This solution is intended only for applications without a sandbox. The LSSharedFile functions used in this solution are available only for applications without a sandbox.)

You are using a list of shared Session Login Items files. This is the list that appears in System Preferences when you check the login items in your profile settings.

A typical application scenario is to check the application settings box, which allows the user to choose whether they want to run the application or not when they log in. If you intend to distribute through the app store, DO NOT install the application to start when you log in by default. You will be rejected :)

So, in this scenario, we will create a property, say in the App Delegate, with the name launchOnLogin, and we will associate the checkbox value with this property.

The getter method will check if our application package identifier is in the general list and will return true or false.

The setter method advertises or removes an item from the general list.

Here it is:

Appdelegate.h

 @property (atomic, assign) BOOL launchOnLogin; 

AppDelegate.m

 - (BOOL)launchOnLogin { LSSharedFileListRef loginItemsListRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); CFArrayRef snapshotRef = LSSharedFileListCopySnapshot(loginItemsListRef, NULL); NSArray* loginItems = [NSMakeCollectable(snapshotRef) autorelease]; NSURL *bundleURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]; for (id item in loginItems) { LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)item; CFURLRef itemURLRef; if (LSSharedFileListItemResolve(itemRef, 0, &itemURLRef, NULL) == noErr) { NSURL *itemURL = (NSURL *)[NSMakeCollectable(itemURLRef) autorelease]; if ([itemURL isEqual:bundleURL]) { return YES; } } } return NO; } - (void)setLaunchOnLogin:(BOOL)launchOnLogin { NSURL *bundleURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]; LSSharedFileListRef loginItemsListRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); if (launchOnLogin) { NSDictionary *properties; properties = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:@"com.apple.loginitem.HideOnLaunch"]; LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItemsListRef, kLSSharedFileListItemLast, NULL, NULL, (CFURLRef)bundleURL, (CFDictionaryRef)properties,NULL); if (itemRef) { CFRelease(itemRef); } } else { LSSharedFileListRef loginItemsListRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); CFArrayRef snapshotRef = LSSharedFileListCopySnapshot(loginItemsListRef, NULL); NSArray* loginItems = [NSMakeCollectable(snapshotRef) autorelease]; for (id item in loginItems) { LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)item; CFURLRef itemURLRef; if (LSSharedFileListItemResolve(itemRef, 0, &itemURLRef, NULL) == noErr) { NSURL *itemURL = (NSURL *)[NSMakeCollectable(itemURLRef) autorelease]; if ([itemURL isEqual:bundleURL]) { LSSharedFileListItemRemove(loginItemsListRef, itemRef); } } } } } 

This is pretty much it. Now, if you make the binding and everything is correct, you will see how your application appears and disappears from the list of system settings in real time.

The part that actually launches the application at login

 // Get the path of the app NSURL *bundleURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]; // Get the list you want to add the path to LSSharedFileListRef loginItemsListRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); // Set the app to be hidden on launch NSDictionary *properties = @{@"com.apple.loginitem.HideOnLaunch": @YES}; // Add the item to the list LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItemsListRef, kLSSharedFileListItemLast, NULL, NULL, (CFURLRef)bundleURL, (CFDictionaryRef)properties,NULL); 

Please note that the code above is a save / release, but it's pretty simple to convert it to ARC if you need it.

Hope this helps.

+14
source

For those who are looking for an updated version of this code compatible with Swift, I made the point: https://gist.github.com/plapier/f8e1dde1b1624dfbb3e4

Just call toggleLaunchAtStartup() from your application. (Most likely, inside the IBAction flag).

And the actual code for reference:

 import Foundation func applicationIsInStartUpItems() -> Bool { return (itemReferencesInLoginItems().existingReference != nil) } func itemReferencesInLoginItems() -> (existingReference: LSSharedFileListItemRef?, lastReference: LSSharedFileListItemRef?) { if let appURL : NSURL = NSURL.fileURLWithPath(NSBundle.mainBundle().bundlePath) { if let loginItemsRef = LSSharedFileListCreate(nil, kLSSharedFileListSessionLoginItems.takeRetainedValue(), nil).takeRetainedValue() as LSSharedFileListRef? { let loginItems: NSArray = LSSharedFileListCopySnapshot(loginItemsRef, nil).takeRetainedValue() as NSArray let lastItemRef: LSSharedFileListItemRef = loginItems.lastObject as! LSSharedFileListItemRef for (index, loginItem) in enumerate(loginItems) { let currentItemRef: LSSharedFileListItemRef = loginItems.objectAtIndex(index) as! LSSharedFileListItemRef if let itemURL = LSSharedFileListItemCopyResolvedURL(currentItemRef, 0, nil) { if (itemURL.takeRetainedValue() as NSURL).isEqual(appURL) { return (currentItemRef, lastItemRef) } } } return (nil, lastItemRef) } } return (nil, nil) } func toggleLaunchAtStartup() { let itemReferences = itemReferencesInLoginItems() let shouldBeToggled = (itemReferences.existingReference == nil) if let loginItemsRef = LSSharedFileListCreate( nil, kLSSharedFileListSessionLoginItems.takeRetainedValue(), nil).takeRetainedValue() as LSSharedFileListRef? { if shouldBeToggled { if let appUrl : CFURLRef = NSURL.fileURLWithPath(NSBundle.mainBundle().bundlePath) { println("Add login item") LSSharedFileListInsertItemURL(loginItemsRef, itemReferences.lastReference, nil, nil, appUrl, nil, nil) } } else { if let itemRef = itemReferences.existingReference { println("Remove login item") LSSharedFileListItemRemove(loginItemsRef,itemRef); } } } } 

Used with Xcode 6.3.2, Swift 1.2

+3
source

You can run the apple script application below from the application to add it to the login element.

 on run args_list tell application "System Events" to make login item at end with properties {path:item 1 of args_list, hidden:false} end run 

Save the above script as AddToLogin.scpt and add it to the project.

Add the code below to launch the application

 NSString *appPath =[[NSBundle mainBundle] bundlePath] ; NSString *scriptPath = [[NSBundle mainBundle] pathForResource:@"AddToLogin" ofType:@"scpt"]; NSArray *argArray; if(scriptPath) { argArray = [NSArray arrayWithObjects:scriptPath, appPath, nil]; NSTask * task = [[NSTask alloc] init]; [task setLaunchPath:@"/usr/bin/osascript"]; [task setArguments:argArray]; [task launch]; [task waitUntilExit]; } 

The link below explains how osascript does the same

http://hints.macworld.com/article.php?story=20111226075701552

+2
source

All Articles