我需要从OSX应用程序运行以下命令:
dscl。 -read / Users / user JPEGPhoto |尾巴-1 | xxd -r -p> /Users/user/Desktop/user.jpg
我尝试了几件事,例如:
func runScript(launchPath:String, scriptName:String) {
let task = NSTask()
task.launchPath = launchPath
task.arguments = NSArray(objects: scriptName)
let pipe = NSPipe()
task.standardOutput = pipe
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output: String = NSString(data: data, encoding: NSUTF8StringEncoding)
}
和
func runCommand(command: String) -> (output: String, exitStatus: Int) {
let tokens = command.componentsSeparatedByString(" ")
let launchPath = tokens[0]
let arguments = tokens[1..<tokens.count]
let task = NSTask()
task.launchPath = launchPath
task.arguments = Array(arguments)
let stdout = NSPipe()
task.standardOutput = stdout
task.launch()
task.waitUntilExit()
let outData = stdout.fileHandleForReading.readDataToEndOfFile()
let outStr = NSString(data: outData, encoding: NSUTF8StringEncoding)
return (outStr, Int(task.terminationStatus))
}
问题是这些方法每次调用都会执行一个命令,因此我必须调用它们三次(dscl / tail / xxd)并且不起作用。
当我在终端中单独尝试它们时,它也没有工作。
有什么建议吗?感谢
更新:
跟随Ken Thomases&#39;很好的建议,这就是它在swift中的样子:
import Collaboration
func saveUserPicture() {
var userImage:NSImage = CBUserIdentity(posixUID: getuid(), authority: CBIdentityAuthority.defaultIdentityAuthority()).image() as NSImage
var userImageData:NSData = NSBitmapImageRep.representationOfImageRepsInArray(userImage.representations, usingType: NSBitmapImageFileType.NSJPEGFileType, properties: nil )
userImageData.writeToFile("/Users/user/Desktop/file.jpg", atomically: true)
}
答案 0 :(得分:0)
您确定需要运行该命令并使用NSTask
吗?该信息应通过直接API提供。
特别是,我认为以下内容可以为您提供用户的图像:
NSImage* image = [[CBUserIdentity identityWithName:@"user" authority:[CBIdentityAuthority defaultIdentityAuthority]] image];
如果你真的想要,你可以将它保存为文件:
NSData* data = [NSBitmapImageRep representationOfImageRepsInArray:image.representations usingType:NSJPEGFileType properties:nil];
[data writeToURL:someURL atomically:YES];
根据您实际提出的问题,您需要为每个命令使用一个NSTask
。您在要模拟的shell命令中为每个管道(NSPipe
)创建|
。您将一个管道设置为第一个任务的输出和第二个任务的输入。您将另一个管道设置为第二个管道的输出和第一个管道的输入。然后运行所有三个任务并等待最后一个完成。
如果需要,可以使用另一个管道来处理每个任务的标准错误和/或上一个任务的输出。确保在等待最后一个任务退出的同时异步读取这些管道(或者更好的是,不要阻止等待最后一个任务,但是回到事件循环并让任务在完成时通知你)。
每个任务的参数应该是一个数组。如果您打算尝试运行这些任务而不是使用正确的API,那么理想情况下,您最好将命令作为数组而不是字符串。根据要模拟的shell的哪些功能,解析字符串是一件很难的事情。因此,对于第一个任务,启动路径为@"dscl"
,参数为@[ @".", @"-read", @"/Users/user", @"JPEGPhoto" ]
。同样适用于其他任务。
为了完整起见,我说你可以运行一个完整的命令行,就像你的原始字符串一样,通过登记shell解析它并为每个子命令运行子进程。将启动路径设置为@"/bin/sh"
,将参数设置为@[ @"-c", @"dscl . -read /Users/user JPEGPhoto | tail -1 | xxd -r -p > /Users/user/Desktop/user.jpg" ]
。不过,我真的不推荐这个。假设您要运行的实际命令是动态的,并且您将以编程方式构建命令行,则很容易产生问题。如果你构建一个包含shell专门处理的字符的字符串,你会得到意想不到的结果,甚至可能做一些危险的事情。另外,就个人而言,构建一个字符串只是觉得错误,以便当你可以直接自己完成原创作品时shell可以分开。