老谭笔记

对神器STPrivilegedTask的改造

OSX开发的朋友应该对STPrivilegedTask都不陌生吧,他可以让你以Root的权限执行一个Task,由于它本身几乎实现了Task的所有接口,所以使用的时候跟NSTask用法一样,所以非常的方便.

虽然STPrivilegedTask已经属于神一般的东西,但最近我在使用的过程中,仍然发现了有以下的问题:

1.如果多次使用的时候,每次都会弹出用户授权的窗口,这样用户体验很不好.

2.如果参数中包含中文的时候,执行会失败(老外向来对这方面的考虑欠周全).

针对以上的问题,我对STPrivilegedTask进行了以下改造:

1.对于第一个问题,我会把授权得到的AuthorizationRef修改成为一个静态的共享对象,这样在一定的时间之内对STPrivilegedTask的使用都不会再弹出授权的窗口了,尤其是对一个操作中多处使用STPrivilegedTask的时候,用户体验就变得非常好了.

2.对于第二个问题,这就属于STPrivilegedTask代码中本身的BUG了,先贴上launch方法中原有代码:

1
2
3
4
5
6
7
8
for (i = 0; i < argumentsCount; i++)
{
NSString *theString = [arguments objectAtIndex:i];
unsigned long stringLength = [theString length];
args[i] = malloc((stringLength + 1) * sizeof(char));
snprintf(args[i], stringLength + 1, "%s", [theString fileSystemRepresentation]);
}

这段代码的目的就是将执行Task的参数转换成一个char*的数组,此处在参数为英文或数字时,是没有问题的,但如果出现特殊的字符,如中文,就有问题了,主要问题是stringLength = [theString length];算出的长度不正确,导致参数转换错误.所以此段代码应该修改为这样:

1
2
3
4
5
6
7
8
9
10
for (short i = 0; i < argumentsCount; i++)
{
NSString *theString = [arguments objectAtIndex:i];
const char *fileRep = [theString fileSystemRepresentation];
size_t size = (strlen(fileRep)+1) * sizeof(char);
args[i] = malloc(size);
memset(args[i], 0, size);
snprintf(args[i], size, "%s", fileRep);
}

这样,该BUG就给解决了,另外加了一个memset,让代码也显得逻辑更为严谨.

好了,还是上传一份我修改后的代码吧,方便也有同样需求或被上面两个问题所困扰程序员们.

代码下载:STPrivilegedTask