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

     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参数一般是传 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.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, 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.app  
            CFURLRef 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)[loginItemsArray  
                                                                                objectAtIndex:i];  
                    //Resolve the item with URL  
                    if (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添加新的方法。

      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文件中,只不过实现的方式不一样罢了。

     

  • 相关阅读:
    Sql Server 2008卸载后再次安装一直报错
    listbox 报错 Cannot have multiple items selected when the SelectionMode is Single.
    Sql Server 2008修改Sa密码
    学习正则表达式
    Sql Server 查询第30条数据到第40条记录数
    Sql Server 复制表
    Sql 常见面试题
    Sql Server 简单查询 异步服务器更新语句
    jQuery stop()用法以及案例展示
    CSS3打造不断旋转的CD封面
  • 原文地址:https://www.cnblogs.com/watchdatalearn2012620/p/3336414.html
Copyright © 2011-2022 走看看