通过ServiceManagement注册LaunchdDaemon

在OSX开发与系统密切相关的软件,经常会使用到高权限的操作,让整个程序都以高权限执行显然是不合适的,通过将高权限的任务封装到独立的子程序,按需要进行调用是比较合理的做法。而常见的做法是通过注册LaunchdDaemon,便可轻松实现开机启动、长驻后台、高权限的需求。

注册LaunchdDaemon的常用方法是通过launchd工具去load一个与Daemon程序相关的标准的plist文件,这个过程一般放在PKG的安装脚本中完成,但当前越来越多的软件摒弃了PKG的打包方式,而是直接选择了打包成app,这样确实提升用户体验,但安装辅助工具的工作都放到了app运行过程中了。由于launchd是需要高权限运行的,而app中提权运行工具并不那么方便。所以便可以考虑通过ServiceManagement的API来完成这样的操作。

ServiceManagement是在10.6就出现的FrameWork,下面就具体介绍一下如何使用相关的API来注册高权限的LaunchdDaemon。

首先你需要在你的工程中创建一个用于LaunchdDaemon的命令行程序的Target,然后为主程序添加工程依赖,并Copy Files中将此子程序拷贝到Contents/Library/LaunchServices目录下。

然后为该子程序添加两个配置文件,一个是程序环境相关的Info.plist,它与普通app中的info.plist一样,添加上一些必须的字段如BundleID,额外需要添加一项SMAuthorizedClients,用于标识可加载或卸载它的主程序,形如下面的代码,指定了它的主程序BundleID为me.tanhao.SMJobDemo。

<key>SMAuthorizedClients</key>
  <array>
    <string>identifier me.tanhao.SMJobDem</string>
  </array>

而另一个是用于Launchd加载时的配置文件,但与以前通过launchd工具去加载的那个plist不同的是不需要添加ProgramArguments项,这些字段都会在注册成功后自动填充。

由于这是一个命令行工具,所以要将两个plist文件编译进Mach-O文件之中,就需要在工程配置中的“Other Linker Flags”中添加额外的参数,形式如下:

-sectcreate __TEXT __info_plist SMJobHelper/SMJobHelper-Info.plist 
-sectcreate __TEXT __launchd_plist SMJobHelper/SMJobHelper-Launchd.plist

主程序要能匹配到合适的子程序,也必须在Info.plist再添加SMPrivilegedExecutables项,用于指定它可以安装的LaunchdDaemon子程序,形如下面的代码,指定

<key>SMPrivilegedExecutables</key>
  <dict>
    <key>SMJobHelper</key>
    <string>identifier me.tanhao.SMJobHelper</string>
  </dict>

然后我们就来完成主程序中注册LaunchdDaemon的代码:

#define kSMJobHelperBunldeID @"SMJobHelper"
- (void)addHelper
{
    NSDictionary *helperInfo = (__bridge NSDictionary*)SMJobCopyDictionary(kSMDomainSystemLaunchd,
                                                                           (__bridge CFStringRef)kSMJobHelperBunldeID);
    if (!helperInfo)
    {
        AuthorizationItem authItem = { kSMRightBlessPrivilegedHelper, 0, NULL, 0 };
        AuthorizationRights authRights = { 1, &authItem };
        AuthorizationFlags flags = kAuthorizationFlagDefaults|
        kAuthorizationFlagInteractionAllowed|
        kAuthorizationFlagPreAuthorize|
        kAuthorizationFlagExtendRights;
        
        AuthorizationRef authRef = NULL;
        OSStatus status = AuthorizationCreate(&authRights, kAuthorizationEmptyEnvironment, flags, &authRef);
        if (status != errAuthorizationSuccess)
        {
            NSLog(@"Failed to create AuthorizationRef, return code %i", status);
        } else
        {
            CFErrorRef error = NULL;
            BOOL result = SMJobBless(kSMDomainSystemLaunchd, (__bridge CFStringRef)kSMJobHelperBunldeID, authRef, &error);
            if (!result)
            {
                NSLog(@"SMJobBless Failed, error : %@",error);
            }
        }
    }
}

编译并运行以上代码(必须签名),首先会弹出一个系统的权限框,然后你输入管理员密码,你的LaunchdDaemon就注册成功了。你会发现子程序被拷贝到了/Library/PrivilegedHelperTools目录,而在/Library/LaunchDaemons也生成了一份与之对应的配置文件,用于launchd进程在合适的时机调用。

官方Demo下载:SMJobBless.zip

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值