目前我所知道的,在cocoa中获得root权限的方法有3种:
1. 通过AuthorizationCopyRights函数
2. 在UI上添加一个锁的样子的控件,然后通过开关这个锁来获取root权限
3. 直接调用Applescript来以root权限执行脚本
其中方法1和2一般用来执行一个shell脚本或者一个可执行文件,方法3则直接执行一个applescript脚本。
当然方法1和2也可以执行一个保存的applescript脚本,方法3也可以用applescript脚本来执行shell或可执行文件。
通过AuthorizationCopyRights
这种方法的缺陷是每次需要root权限都要执行一次,或者必须在程序开启的时候获取root权限。
请看下面的代码:
OSStatus status; AuthorizationRef authRef; status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authRef); AuthorizationRights authRights; AuthorizationItem authItems[1]; authItems[0].name = kAuthorizationRightExecute; authRights.count = sizeof(authItems) / sizeof(authItems[0]); authRights.items = authItems; AuthorizationFlags authFlags = kAuthorizationFlagDefaults | kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed; status = AuthorizationCopyRights(authRef, &authRights, kAuthorizationEmptyEnvironment, authFlags, NULL); if(status != errAuthorizationSuccess) { NSLog(@"Copy rights unsuccessful: %d",status); } .......... //中间省略 status = AuthorizationExecuteWithPrivileges(authRef, 可执行文件的路径, kAuthorizationFlagDefaults, 可执行文件需要的参数, nil); if (status != errAuthorizationSuccess) { NSLog(@"Error: %d", status); }
在UI上加一个锁
这个方法比较灵活,打开锁之后任何需要root权限的地方都可以直接用了,是我最推荐的一个方法
1. 首先给自己的项目添加两个framework。Build phrase -> Link Binary With Libraries 添加Security.framework 和 SecurityInterface.framework.
2. 在UI上拖拽进去一个Custom view控件,然后把它的Custom class设为SFAuthorizationView
3. 在AppDelegate.h中添加代码如下:
........... #import <SecurityInterface/SFAuthorizationView.h> #import <SystemConfiguration/SystemConfiguration.h> @interface AppDelegate : NSObject <NSApplicationDelegate> { ............ IBOutlet SFAuthorizationView *authView; ............ } -(BOOL)isUnlocked;
添加两个头文件,并把custom view跟一个SFAuthorizationView 变量关联起来。
4. 在AppDelegate.m中添加如下代码:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Insert code here to initialize your application AuthorizationItem items = {kAuthorizationRightExecute,0,NULL,0}; AuthorizationRights rights = {1,&items}; [authView setAuthorizationRights:&rights]; authView.delegate =self; [authView updateStatus:nil]; } -(BOOL)isUnlocked { return [authView authorizationState] == SFAuthorizationViewUnlockedState; } -(void)authorizationViewDidAuthorize:(SFAuthorizationView *)view { } -(void)authorizationViewDidDeauthorize:(SFAuthorizationView *)view { } -(void)doSomething { ............. OSErr processErr = AuthorizationExecuteWithPrivileges([[authView authorization] authorizationRef], [binaryPath UTF8String], kAuthorizationFlagDefaults, (char* const*)args, nil); if (processErr != errAuthorizationSuccess) { NSLog(@"Error: %d", processErr); } ............. }
applicationDidFinishLaunching 首先在程序启动的时候初始化authView
isUnlocked 判断那个锁是否锁住
authorizationViewDidAuthorize 和 authorizationViewDidDeauthorize 分别在锁被打开和被锁住的时候触发,你可以做你自己想做的事情,比如把按钮变灰之类的
doSomething 就可以利用authView authorization 来授权AuthorizationExecuteWithPrivileges进行root权限的操作了
可参考http://bdunagan.com/2009/12/13/system-preferences-pane-lock/
利用applescript来执行root操作
NSDictionary *errorInfo = [NSDictionary new]; NSString *script = [NSString stringWithFormat:@"do shell script \"%@\" with administrator privileges", fullScript]; NSAppleScript *appleScript = [[NSAppleScript new] initWithSource:script]; NSAppleEventDescriptor * eventResult = [appleScript executeAndReturnError:&errorInfo]; // Check errorInfo if (! eventResult) { // do something you want }