一 写plist到~/Library/LaunchAgents/ 目录下

// 配置开机默认启动
-(void)installDaemon{NSString* launchFolder = [NSString stringWithFormat:@"%@/Library/LaunchAgents",NSHomeDirectory()];NSString * boundleID = [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleIdentifierKey]; NSString* dstLaunchPath = [launchFolder stringByAppendingFormat:@"/%@.plist",boundleID];NSFileManager* fm = [NSFileManager defaultManager];BOOL isDir = NO;//已经存在启动项中,就不必再创建if ([fm fileExistsAtPath:dstLaunchPath isDirectory:&isDir] && !isDir) {return;}//下面是一些配置NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];NSMutableArray* arr = [[NSMutableArray alloc] init];[arr addObject:[[NSBundle mainBundle] executablePath]];[arr addObject:@"-runMode"];[arr addObject:@"autoLaunched"];[dict setObject:[NSNumber numberWithBool:true] forKey:@"RunAtLoad"];[dict setObject:boundleID forKey:@"Label"];[dict setObject:arr forKey:@"ProgramArguments"];isDir = NO;if (![fm fileExistsAtPath:launchFolder isDirectory:&isDir] && isDir) {[fm createDirectoryAtPath:launchFolder withIntermediateDirectories:NO attributes:nil error:nil];}[dict writeToFile:dstLaunchPath atomically:NO];[arr release]; arr = nil;[dict release]; dict = nil;
}

关于启动项的配置可以去开发文档搜索:Creating launchd Daemons and Agents。

取消开机启动则只要删除~/Library/LaunchAgents/ 目录下相应的plist文件即可。

// 取消配置开机默认启动
-(void)unInstallDaemon{NSString* launchFolder = [NSString stringWithFormat:@"%@/Library/LaunchAgents",NSHomeDirectory()];BOOL isDir = NO;NSFileManager* fm = [NSFileManager defaultManager];if (![fm fileExistsAtPath:launchFolder isDirectory:&isDir] && isDir) {return;}NSString * boundleID = [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleIdentifierKey]; NSString* srcLaunchPath = [launchFolder stringByAppendingFormat:@"/%@.plist",boundleID];[fm removeItemAtPath:srcLaunchPath error:nil];
}

二.使用LoginItemsAE

在开发文档中搜索LoginItemsAE即可搜到它的源码,包含LoginItemsAE.c和LoginItemsAE.h两个文件。其原理是写配置信息到~/Library/Preferences/com.apple.loginitems.plist 文件。打开com.apple.loginitems.plist文件找到CustomListItems那一项,展开就可以看到开机启动项的一些信息(包括app名称,所在路径。。。)

图1:com.apple.loginitems.plist 开机启动项内容

下面简单介绍下LoginItemsAE.h 中的几个API。

//返回开机启动项列表,传入itemsPtr地址即可,
extern OSStatus LIAECopyLoginItems(CFArrayRef *itemsPtr);
//添加开机启动项,hideIt参数一般是传 NO
extern OSStatus LIAEAddURLAtEnd(CFURLRef item,     Boolean hideIt);
//移除开机启动项
extern OSStatus LIAERemove(CFIndex itemIndex);

是不是觉得上面的接口不是很好用呢,特别是移除启动项的那个接口,必须得知道要移除的index,如果能根据文件路径移除就好了。下面用Objective-C语法重新封装这几个接口,更方便调用。

#import "UKLoginItemRegistry.h"@implementation UKLoginItemRegistry+(NSArray*)    allLoginItems
{NSArray*   itemsList = nil;OSStatus   err = LIAECopyLoginItems( (CFArrayRef*) &itemsList );  // Take advantage of toll-free bridging.if( err != noErr ){NSLog(@"Couldn't list login items error %ld", err);return nil;}return [itemsList autorelease];
}+(BOOL)       addLoginItemWithPath: (NSString*)path hideIt: (BOOL)hide
{NSURL* url = [NSURL fileURLWithPath: path];return [self addLoginItemWithURL: url hideIt: hide];
}//根据文件路径移除启动项
+(BOOL)        removeLoginItemWithPath: (NSString*)path
{int        idx = [self indexForLoginItemWithPath: path];return (idx != -1) && [self removeLoginItemAtIndex: idx];    // Found item? Remove it and return success flag. Else return NO.
}+(BOOL)       addLoginItemWithURL: (NSURL*)url hideIt: (BOOL)hide         // Main bottleneck for adding a login item.
{OSStatus err = LIAEAddURLAtEnd( (CFURLRef) url, hide );   // CFURLRef is toll-free bridged to NSURL.if( err != noErr )NSLog(@"Couldn't add login item error %ld", err);return( err == noErr );
}+(BOOL)       removeLoginItemAtIndex: (int)idx            // Main bottleneck for getting rid of a login item.
{OSStatus err = LIAERemove( idx );if( err != noErr )NSLog(@"Couldn't remove login intem error %ld", err);return( err == noErr );
}+(int)        indexForLoginItemWithURL: (NSURL*)url       // Main bottleneck for finding a login item in the list.
{NSArray*       loginItems = [self allLoginItems];NSEnumerator*    enny = [loginItems objectEnumerator];NSDictionary* currLoginItem = nil;int                x = 0;while(( currLoginItem = [enny nextObject] )){if( [[currLoginItem objectForKey: UKLoginItemURL] isEqualTo: url] )return x;x++;}return -1;
}+(int)        indexForLoginItemWithPath: (NSString*)path
{NSURL* url = [NSURL fileURLWithPath: path];return [self indexForLoginItemWithURL: url];
}+(BOOL)       removeLoginItemWithURL: (NSURL*)url
{int        idx = [self indexForLoginItemWithURL: url];return (idx != -1) && [self removeLoginItemAtIndex: idx];  // Found item? Remove it and return success flag. Else return NO.
}@end

上面的代码是不是觉得亲切多了啊?

不过这几个接口有点缺陷:只能用i386来编译,用x86_64编译会报错的。

三. 使用LaunchServices修改启动项

可以使用LaunchServices/LSSharedFileList.h 里面的方法来更改启动项,但是这些方法只支持10.5及以上的系统。下面简单的介绍下这些方法。

//这个方法返回启动项列表
extern LSSharedFileListRef
LSSharedFileListCreate(CFAllocatorRef   inAllocator,CFStringRef      inListType,CFTypeRef        listOptions)
//添加新的启动项
extern LSSharedFileListItemRef LSSharedFileListInsertItemURL(LSSharedFileListRef       inList,LSSharedFileListItemRef   insertAfterThisItem,CFStringRef               inDisplayName,IconRef                   inIconRef,CFURLRef                  inURL,CFDictionaryRef           inPropertiesToSet,CFArrayRef                inPropertiesToClear)
//移除启动项
extern OSStatus LSSharedFileListItemRemove(LSSharedFileListRef       inList,LSSharedFileListItemRef   inItem)
//最后一个方法用来解析启动项的 URL,用来检索启动项列表里的东西
extern OSStatus LSSharedFileListItemResolve(LSSharedFileListItemRef   inItem,UInt32                    inFlags,CFURLRef *                outURL,FSRef *                   outRef)

使用下面两个方法来封装上面的这些API,使更易于使用。你也可以改成传入app路径添加启动项。- (void) addAppAsLoginItem:(NSString *)appPath,把这句NSString * appPath = [[NSBundle mainBundle] bundlePath];注视掉就行了。

-(void) addAppAsLoginItem{NSString * appPath = [[NSBundle mainBundle] bundlePath];// This will retrieve the path for the application// For example, /Applications/test.appCFURLRef url = (CFURLRef)[NSURL fileURLWithPath:appPath]; // Create a reference to the shared file list.// We are adding it to the current user only.// If we want to add it all users, use// kLSSharedFileListGlobalLoginItems instead of//kLSSharedFileListSessionLoginItemsLSSharedFileListRef loginItems = LSSharedFileListCreate(NULL,kLSSharedFileListSessionLoginItems, NULL);if (loginItems) {//Insert an item to the list.LSSharedFileListItemRef item = LSSharedFileListInsertItemURL(loginItems,kLSSharedFileListItemLast, NULL, NULL,url, NULL, NULL);if (item){CFRelease(item);}}CFRelease(loginItems);
}-(void) deleteAppFromLoginItem{NSString * appPath = [[NSBundle mainBundle] bundlePath];// This will retrieve the path for the application// For example, /Applications/test.appCFURLRef url = (CFURLRef)[NSURL fileURLWithPath:appPath]; // Create a reference to the shared file list.LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL,kLSSharedFileListSessionLoginItems, NULL);if (loginItems) {UInt32 seedValue;//Retrieve the list of Login Items and cast them to// a NSArray so that it will be easier to iterate.NSArray  *loginItemsArray = (NSArray *)LSSharedFileListCopySnapshot(loginItems, &seedValue);int i = 0;for(i ; i< [loginItemsArray count]; i++){LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)[loginItemsArrayobjectAtIndex:i];//Resolve the item with URLif (LSSharedFileListItemResolve(itemRef, 0, (CFURLRef*) &url, NULL) == noErr) {NSString * urlPath = [(NSURL*)url path];if ([urlPath compare:appPath] == NSOrderedSame){LSSharedFileListItemRemove(loginItems,itemRef);}}}[loginItemsArray release];}
}

详情请打开:http://cocoatutorial.grapewave.com/2010/02/creating-andor-removing-a-login-item/

四. 使用NSUserDefaults修改启动项

下面通过分类给NSUserDefaults添加新的方法。

@implementation NSUserDefaults (Additions)- (BOOL)addApplicationToLoginItems:(NSString *)path {NSDictionary *domain = [self persistentDomainForName:@"loginwindow"];NSArray *apps = [domain objectForKey:@"AutoLaunchedApplicationDictionary"];NSArray *matchingApps = [apps filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"Path CONTAINS %@", path]];if ([matchingApps count] == 0) {NSMutableDictionary *newDomain = [domain mutableCopy];NSMutableArray *newApps = [[apps mutableCopy] autorelease];NSDictionary *app = [NSDictionary dictionaryWithObjectsAndKeys:path, @"Path", [NSNumber numberWithBool:NO], @"Hide", nil];[newApps addObject:app];[newDomain setObject:newApps forKey:@"AutoLaunchedApplicationDictionary"];[self setPersistentDomain:newDomain forName:@"loginwindow"];return [self synchronize];}return NO;
}- (BOOL)removeApplicationFromLoginItems:(NSString *)name {NSDictionary *domain = [self persistentDomainForName:@"loginwindow"];NSArray *apps = [domain objectForKey:@"AutoLaunchedApplicationDictionary"];NSArray *newApps = [apps filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"not Path CONTAINS %@", name]];if (![apps isEqualToArray:newApps]) {NSMutableDictionary *newDomain = [domain mutableCopy];[newDomain setObject:newApps forKey:@"AutoLaunchedApplicationDictionary"];[self setPersistentDomain:newDomain forName:@"loginwindow"];return [self synchronize];}return NO;
}@end

详情请打开:http://www.danandcheryl.com/2011/02/how-to-modify-the-dock-or-login-items-on-os-x

后面三种方法都是写配置到~/Library/Preferences/com.apple.loginitems.plist文件中,只不过实现的方式不一样罢了。

Cocoa -- 添加和移除开机启动项相关推荐

  1. win10添加应用程序到开机启动项

    方法一: 1.首先创建或者找到需要添加的程序的快捷方式 2.打开运行对话框(win键+R),输入命令 shell:startup 会直接弹出启动项对应的目录,把应用程序快捷方式复制到启动目录 注:本方 ...

  2. centos7 设置开机启动项

    高端的废话就是没有引言这种废话. 1.这里我已我的centos7为例输入: systemctl list-unit-files   #查看开机启动表如图下: 最左边就是服务 ,最右边就是状态 .如当你 ...

  3. w ndows10怎么关闭启动项,开机启动项怎么设置?Win10启动项修改技巧

    注:本教程适用于Win7.Win8.Win8.1和Win10系统 Win10电脑开机慢怎么办?其实不必要的开机启动项占了很大一部分原因,那么禁用或删除某些开机启动项就可以明显地提高电脑开机速度:而有些 ...

  4. windows 增加开机启动服务器,Windows Server2012删除或添加开机启动项的方法

    Windows Server2012怎么删除或添加开机启动项?Windows Server 2012跟Windows8一样,拥有全新的任务管理器.Windows Server 2012可以随意在服务器 ...

  5. linux 添加开机启动项的三种方法。

    原文地址: https://blog.csdn.net/lylload/article/details/79488968 Shell环境变量配置文件:https://blog.csdn.net/yzs ...

  6. Ubuntu下添加开机启动项的2种方法

    Ubuntu下添加开机启动项的方法 1.方法一,编辑rc.loacl脚本 Ubuntu开机之后会执行/etc/rc.local文件中的脚本, 所以我们可以直接在/etc/rc.local中添加启动脚本 ...

  7. ​linux 添加开机启动项的三种方法

    linux 添加开机启动项的三种方法. (1)编辑文件 /etc/rc.local 输入命令:vim /etc/rc.local 将出现类似如下的文本片段: #!/bin/sh # # This sc ...

  8. windows快速添加开机启动项/禁用开机启动项

    启动项就是开机后系统自动加载运行的程序,一些软件设置成开机启动后会更方便我们的使用.下面就和大家分享一个win10系统添加开机启动项的小技巧 1.按下 win+r 快捷键,打开运行窗口,输入shell ...

  9. Powershell 添加开机启动项

    在某些自动化任务中,需要让程序开机启动.Powershell 添加开机启动项的代码如下: $RunPath = "HKLM:\SOFTWARE\Microsoft\Windows\Curre ...

最新文章

  1. 一个球从100m高度自由落下,第10次反弹多高
  2. 打开闪光灯java代码_android 拍照带水印(可打开闪光灯功能)
  3. [POI2005]BAN-Bank Notes
  4. FPGA FIFO深度计算
  5. Android之用Intent.FLAG_ACTIVITY_CLEAR_TOP解决界面重复拉起问题
  6. 需要规范日志格式_Node开发的日志规范
  7. GITEE提交代码时出现“文本是相同的,但文件不匹配“问题解决方法
  8. python(3.10,Win10 64位)的wordcloud安装
  9. oracle 企业管理器网页打不开 解决https://localhost:1158/em问题
  10. 苹果吃鸡蓝牙耳机推荐哪个?性价比高的游戏蓝牙耳机推荐
  11. 计算机保持在线的几种方法,还在为智能盒子上电影软件收费烦恼?教你几个盒子上看大片的方法...
  12. 计算机应用对字数的要求,信息系统项目管理师考试论文字数要求是多少,没达标会扣多少分...
  13. 咸鱼Maya笔记—Maya 倒角命令
  14. FPGA(四):FPGA通过查表的方式生成正弦波
  15. 免费开源的图片修复工具Lama Cleaner
  16. etcd基本使用与安装
  17. r5处理器_R5-4500U / R5-4600U笔记本推荐
  18. Ubuntu18.04 安装 Idea 2018.2 Ultimate
  19. mtk交叉编译工具链
  20. Windows下mklink使用, 硬链接, 软链接和快捷方式的区别

热门文章

  1. 2018运动场景内运动检测调研文章
  2. 阿里云全站加速 DCDN 升级
  3. c#实现批量坐标方位角计算
  4. 【Python基础】第十六篇 | 面向对象之高级篇
  5. ANSI、C99、C11 标准区别详解
  6. UE4使用OpenCV插件调用电脑摄像头
  7. 图像质量评估指标(3) 特征相似度FSIM
  8. 如何用SaaS科技赋能中小企业管理
  9. 智能学习 | MATLAB实现Bee-CNN蜜蜂算法优化卷积神经网络图像分类预测
  10. intersect 相交 范围_关于CAD二次开发中(范围线自相交)相交线的问题