zoukankan      html  css  js  c++  java
  • 添加移除开机启动项

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

    [plain] view plaincopy
     
    1. // 配置开机默认启动  
    2. -(void)installDaemon{  
    3.     NSString* launchFolder = [NSString stringWithFormat:@"%@/Library/LaunchAgents",NSHomeDirectory()];  
    4.     NSString * boundleID = [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleIdentifierKey];   
    5.     NSString* dstLaunchPath = [launchFolder stringByAppendingFormat:@"/%@.plist",boundleID];  
    6.     NSFileManager* fm = [NSFileManager defaultManager];  
    7.     BOOL isDir = NO;  
    8.     //已经存在启动项中,就不必再创建  
    9.     if ([fm fileExistsAtPath:dstLaunchPath isDirectory:&isDir] && !isDir) {  
    10.         return;  
    11.     }  
    12.     //下面是一些配置  
    13.     NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];  
    14.     NSMutableArray* arr = [[NSMutableArray alloc] init];  
    15.     [arr addObject:[[NSBundle mainBundle] executablePath]];  
    16.     [arr addObject:@"-runMode"];  
    17.     [arr addObject:@"autoLaunched"];  
    18.     [dict setObject:[NSNumber numberWithBool:true] forKey:@"RunAtLoad"];  
    19.     [dict setObject:boundleID forKey:@"Label"];  
    20.     [dict setObject:arr forKey:@"ProgramArguments"];  
    21.     isDir = NO;  
    22.     if (![fm fileExistsAtPath:launchFolder isDirectory:&isDir] && isDir) {  
    23.         [fm createDirectoryAtPath:launchFolder withIntermediateDirectories:NO attributes:nil error:nil];  
    24.     }  
    25.     [dict writeToFile:dstLaunchPath atomically:NO];  
    26.     [arr release];  arr = nil;  
    27.     [dict release]; dict = nil;  
    28. }  

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

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

    [plain] view plaincopy
     
    1. // 取消配置开机默认启动  
    2. -(void)unInstallDaemon{  
    3.     NSString* launchFolder = [NSString stringWithFormat:@"%@/Library/LaunchAgents",NSHomeDirectory()];  
    4.     BOOL isDir = NO;  
    5.     NSFileManager* fm = [NSFileManager defaultManager];  
    6.     if (![fm fileExistsAtPath:launchFolder isDirectory:&isDir] && isDir) {  
    7.         return;  
    8.     }  
    9.     NSString * boundleID = [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleIdentifierKey];   
    10.     NSString* srcLaunchPath = [launchFolder stringByAppendingFormat:@"/%@.plist",boundleID];  
    11.     [fm removeItemAtPath:srcLaunchPath error:nil];  
    12. }  

    二.使用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。

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

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

    [plain] view plaincopy
     
    1. #import "UKLoginItemRegistry.h"  
    2.   
    3.   
    4. @implementation UKLoginItemRegistry  
    5.   
    6. +(NSArray*) allLoginItems  
    7. {  
    8.     NSArray*    itemsList = nil;  
    9.     OSStatus    err = LIAECopyLoginItems( (CFArrayRef*) &itemsList );   // Take advantage of toll-free bridging.  
    10.     if( err != noErr )  
    11.     {  
    12.         NSLog(@"Couldn't list login items error %ld", err);  
    13.         return nil;  
    14.     }  
    15.       
    16.     return [itemsList autorelease];  
    17. }  
    18.   
    19. +(BOOL)     addLoginItemWithPath: (NSString*)path hideIt: (BOOL)hide  
    20. {  
    21.     NSURL*  url = [NSURL fileURLWithPath: path];  
    22.       
    23.     return [self addLoginItemWithURL: url hideIt: hide];  
    24. }  
    25.   
    26. //根据文件路径移除启动项  
    27. +(BOOL)     removeLoginItemWithPath: (NSString*)path  
    28. {  
    29.     int     idx = [self indexForLoginItemWithPath: path];  
    30.       
    31.     return (idx != -1) && [self removeLoginItemAtIndex: idx];   // Found item? Remove it and return success flag. Else return NO.  
    32. }  
    33.   
    34. +(BOOL)     addLoginItemWithURL: (NSURL*)url hideIt: (BOOL)hide         // Main bottleneck for adding a login item.  
    35. {  
    36.     OSStatus err = LIAEAddURLAtEnd( (CFURLRef) url, hide ); // CFURLRef is toll-free bridged to NSURL.  
    37.       
    38.     if( err != noErr )  
    39.         NSLog(@"Couldn't add login item error %ld", err);  
    40.       
    41.     return( err == noErr );  
    42. }  
    43.   
    44.   
    45. +(BOOL)     removeLoginItemAtIndex: (int)idx            // Main bottleneck for getting rid of a login item.  
    46. {  
    47.     OSStatus err = LIAERemove( idx );  
    48.       
    49.     if( err != noErr )  
    50.         NSLog(@"Couldn't remove login intem error %ld", err);  
    51.       
    52.     return( err == noErr );  
    53. }  
    54.   
    55.   
    56. +(int)      indexForLoginItemWithURL: (NSURL*)url       // Main bottleneck for finding a login item in the list.  
    57. {  
    58.     NSArray*        loginItems = [self allLoginItems];  
    59.     NSEnumerator*   enny = [loginItems objectEnumerator];  
    60.     NSDictionary*   currLoginItem = nil;  
    61.     int             x = 0;  
    62.       
    63.     while(( currLoginItem = [enny nextObject] ))  
    64.     {  
    65.         if( [[currLoginItem objectForKey: UKLoginItemURL] isEqualTo: url] )  
    66.             return x;  
    67.           
    68.         x++;  
    69.     }  
    70.       
    71.     return -1;  
    72. }  
    73.   
    74. +(int)      indexForLoginItemWithPath: (NSString*)path  
    75. {  
    76.     NSURL*  url = [NSURL fileURLWithPath: path];  
    77.       
    78.     return [self indexForLoginItemWithURL: url];  
    79. }  
    80.   
    81.   
    82. +(BOOL)     removeLoginItemWithURL: (NSURL*)url  
    83. {  
    84.     int     idx = [self indexForLoginItemWithURL: url];  
    85.       
    86.     return (idx != -1) && [self removeLoginItemAtIndex: idx];   // Found item? Remove it and return success flag. Else return NO.  
    87. }  
    88.   
    89. @end  

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

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

    三. 使用LaunchServices修改启动项

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

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

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

    [plain] view plaincopy
     
    1. -(void) addAppAsLoginItem{  
    2.     NSString * appPath = [[NSBundle mainBundle] bundlePath];  
    3.       
    4.     // This will retrieve the path for the application  
    5.     // For example, /Applications/test.app  
    6.     CFURLRef url = (CFURLRef)[NSURL fileURLWithPath:appPath];   
    7.       
    8.     // Create a reference to the shared file list.  
    9.     // We are adding it to the current user only.  
    10.     // If we want to add it all users, use  
    11.     // kLSSharedFileListGlobalLoginItems instead of  
    12.     //kLSSharedFileListSessionLoginItems  
    13.     LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL,  
    14.                                                             kLSSharedFileListSessionLoginItems, NULL);  
    15.     if (loginItems) {  
    16.         //Insert an item to the list.  
    17.         LSSharedFileListItemRef item = LSSharedFileListInsertItemURL(loginItems,  
    18.                                                                      kLSSharedFileListItemLast, NULL, NULL,  
    19.                                                                      url, NULL, NULL);  
    20.         if (item){  
    21.             CFRelease(item);  
    22.         }  
    23.     }  
    24.       
    25.     CFRelease(loginItems);  
    26. }  
    27.   
    28. -(void) deleteAppFromLoginItem{  
    29.     NSString * appPath = [[NSBundle mainBundle] bundlePath];  
    30.       
    31.     // This will retrieve the path for the application  
    32.     // For example, /Applications/test.app  
    33.     CFURLRef url = (CFURLRef)[NSURL fileURLWithPath:appPath];   
    34.       
    35.     // Create a reference to the shared file list.  
    36.     LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL,  
    37.                                                             kLSSharedFileListSessionLoginItems, NULL);  
    38.       
    39.     if (loginItems) {  
    40.         UInt32 seedValue;  
    41.         //Retrieve the list of Login Items and cast them to  
    42.         // a NSArray so that it will be easier to iterate.  
    43.         NSArray  *loginItemsArray = (NSArray *)LSSharedFileListCopySnapshot(loginItems, &seedValue);  
    44.         int i = 0;  
    45.         for(i ; i< [loginItemsArray count]; i++){  
    46.             LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)[loginItemsArray  
    47.                                                                         objectAtIndex:i];  
    48.             //Resolve the item with URL  
    49.             if (LSSharedFileListItemResolve(itemRef, 0, (CFURLRef*) &url, NULL) == noErr) {  
    50.                 NSString * urlPath = [(NSURL*)url path];  
    51.                 if ([urlPath compare:appPath] == NSOrderedSame){  
    52.                     LSSharedFileListItemRemove(loginItems,itemRef);  
    53.                 }  
    54.             }  
    55.         }  
    56.         [loginItemsArray release];  
    57.     }  
    58. }  

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

    四. 使用NSUserDefaults修改启动项

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

    [plain] view plaincopy
     
    1. @implementation NSUserDefaults (Additions)  
    2.   
    3. - (BOOL)addApplicationToLoginItems:(NSString *)path {  
    4.     NSDictionary *domain = [self persistentDomainForName:@"loginwindow"];  
    5.     NSArray *apps = [domain objectForKey:@"AutoLaunchedApplicationDictionary"];  
    6.     NSArray *matchingApps = [apps filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"Path CONTAINS %@", path]];  
    7.     if ([matchingApps count] == 0) {  
    8.         NSMutableDictionary *newDomain = [domain mutableCopy];  
    9.         NSMutableArray *newApps = [[apps mutableCopy] autorelease];  
    10.         NSDictionary *app = [NSDictionary dictionaryWithObjectsAndKeys:path, @"Path", [NSNumber numberWithBool:NO], @"Hide", nil];  
    11.         [newApps addObject:app];  
    12.         [newDomain setObject:newApps forKey:@"AutoLaunchedApplicationDictionary"];  
    13.         [self setPersistentDomain:newDomain forName:@"loginwindow"];  
    14.         return [self synchronize];  
    15.     }  
    16.     return NO;  
    17. }  
    18.   
    19. - (BOOL)removeApplicationFromLoginItems:(NSString *)name {  
    20.     NSDictionary *domain = [self persistentDomainForName:@"loginwindow"];  
    21.     NSArray *apps = [domain objectForKey:@"AutoLaunchedApplicationDictionary"];  
    22.     NSArray *newApps = [apps filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"not Path CONTAINS %@", name]];  
    23.     if (![apps isEqualToArray:newApps]) {  
    24.         NSMutableDictionary *newDomain = [domain mutableCopy];  
    25.         [newDomain setObject:newApps forKey:@"AutoLaunchedApplicationDictionary"];  
    26.         [self setPersistentDomain:newDomain forName:@"loginwindow"];  
    27.         return [self synchronize];  
    28.     }  
    29.     return NO;  
    30. }  
    31.   
    32. @end  



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

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

  • 相关阅读:
    Python学习日记(三) 学习使用dict
    Python学习日记(二) list操作
    Python学习日记(一) String函数使用
    Linux 下查找并删除文件命令
    spring mvc处理静态文件
    集合工具类CollectionUtils、ListUtils、SetUtils、MapUtils探究(转)
    如何选择IO流
    java并发框架Executor介绍
    mybatis如何传入一个list参数
    大规模SOA系统中的分布事务思考
  • 原文地址:https://www.cnblogs.com/conanwin/p/4670729.html
Copyright © 2011-2022 走看看