Cocoa -- 添加和移除开机启动项

Cocoa -- 添加和移除开机启动项,第1张

概述一 写plist到~/Library/LaunchAgents/ 目录下 // 配置开机默认启动-(void)installDaemon{ NSString* launchFolder = [NSString stringWithFormat:@"%@/Library/LaunchAgents",NSHomeDirectory()]; NSString * boundleID = [[NSB  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.cLoginItemSAE.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修改启动项

可以使用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修改启动项

下面通过分类给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 -- 添加和移除开机启动项所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1059161.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存