// 配置开机默认启动-(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参数一般是传 NOextern 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/LSSharedfileList.h 里面的方法来更改启动项,但是这些方法只支持10.5及以上的系统。下面简单的介绍下这些方法。
//这个方法返回启动项列表extern LSSharedfileListRefLSSharedfileListCreate( 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.app CFURLRef 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 //kLSSharedfileListSessionLoginItems LSSharedfileListRef loginItems = LSSharedfileListCreate(NulL,kLSSharedfileListSessionLoginItems,NulL); if (loginItems) { //Insert an item to the List. LSSharedfileListItemRef item = LSSharedfileListInsertItemURL(loginItems,kLSSharedfileListItemLast,NulL,url,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.app CFURLRef url = (CFURLRef)[NSURL fileURLWithPath:appPath]; // Create a reference to the shared file List. LSSharedfileListRef loginItems = LSSharedfileListCreate(NulL,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)[loginItemsArray objectAtIndex:i]; //Resolve the item with URL if (LSSharedfileListItemResolve(itemRef,(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添加新的方法。
@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 -- 添加和移除开机启动项全部内容,希望文章能够帮你解决Cocoa -- 添加和移除开机启动项所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)