在 NSTask 中设置启动路径时如何捕获错误
How to catch error when setting launchpath in NSTask
我正在尝试 运行 在 mac (10.10) 上使用 swift 2 的命令行工具:
let task = NSTask()
task.launchPath = "/path/to/wrong/binary"
task.launch()
// NSPipe() stuff to catch output
task.waitUntilExit()
// never reached
if (task.terminationStatus != 0){
NSLog("uh oh")
}
由于路径错误,我的程序死掉了launch path not accessible
。但是,我不知道如何捕获此错误。在 task.launch()
周围使用 do { try } catch {}
不起作用,因为它不会抛出异常,查看 terminationStatus
也不起作用,因为它从未达到。
怎么才能抓错launchPath
?
Apple Swift 版本 2.1.1 (swiftlang-700.1.101.15 clang-700.1.81)
目标:x86_64-apple-darwin14.5.0
不幸的是,没有机会捕获运行时异常。使用 try / catch 你可以从错误中恢复,而不是从运行时异常中恢复。您可以创建自己的异常处理程序,但您仍然无法从中恢复。尝试从 NSTask 中获取一些常见的 shell 并将命令作为参数,然后使用管道将 return os 错误发送给您自己的代码。
import Foundation
let task = Process()
let pipe = Pipe()
task.launchPath = "/bin/bash"
task.arguments = ["-c","unknown"]
task.standardOutput = pipe
task.launch()
let handle = pipe.fileHandleForReading
let data = handle.readDataToEndOfFile()
let dataString = String(data: data, encoding: .utf8)
print(dataString ?? "")
将打印
/bin/bash: unknown: command not found
你不应该抓住它。您的计算机,即您的应用 运行 所在的本地环境,被视为可靠的媒介。因此,NSTask 被设计为期望你提供给它的任何路径都保证存在。这很好,因为人们通常使用 NSTask 来启动标准系统可执行文件(bash
、diff
、rsync
等)。路径错误的崩溃旨在帮助您轻松找到代码中的错误。如果您要启动自己的 custom-built 嵌入应用程序包中的二进制文件,您应该 真的 改用 XPC。
如果您确实需要使用 NSTask 来启动不可靠的路径,那么在创建对象之前,您需要使用 NSFileManager 的 fileExistsAtPath(_:isDirectory:)
手动验证路径并做出相应的反应。如果连 POSIX 权限标志都不可靠(此时,您的应用程序可能存在一些严重的安全问题;如果这是一个消费者应用程序项目,我建议您重新考虑您的设计),您还需要检查文件的 NSFilePosixPermissions
属性以确保它是可执行的。
在 Mac OS X High Sierra 中,launch()
已弃用。
您可以使用 run()
代替:
let process = Process()
// ...
do {
process.run()
} catch let error as NSError {
print(error.localizedDescription)
// ...
}
另请参阅 Apple Dev Docs
我正在尝试 运行 在 mac (10.10) 上使用 swift 2 的命令行工具:
let task = NSTask()
task.launchPath = "/path/to/wrong/binary"
task.launch()
// NSPipe() stuff to catch output
task.waitUntilExit()
// never reached
if (task.terminationStatus != 0){
NSLog("uh oh")
}
由于路径错误,我的程序死掉了launch path not accessible
。但是,我不知道如何捕获此错误。在 task.launch()
周围使用 do { try } catch {}
不起作用,因为它不会抛出异常,查看 terminationStatus
也不起作用,因为它从未达到。
怎么才能抓错launchPath
?
Apple Swift 版本 2.1.1 (swiftlang-700.1.101.15 clang-700.1.81) 目标:x86_64-apple-darwin14.5.0
不幸的是,没有机会捕获运行时异常。使用 try / catch 你可以从错误中恢复,而不是从运行时异常中恢复。您可以创建自己的异常处理程序,但您仍然无法从中恢复。尝试从 NSTask 中获取一些常见的 shell 并将命令作为参数,然后使用管道将 return os 错误发送给您自己的代码。
import Foundation
let task = Process()
let pipe = Pipe()
task.launchPath = "/bin/bash"
task.arguments = ["-c","unknown"]
task.standardOutput = pipe
task.launch()
let handle = pipe.fileHandleForReading
let data = handle.readDataToEndOfFile()
let dataString = String(data: data, encoding: .utf8)
print(dataString ?? "")
将打印
/bin/bash: unknown: command not found
你不应该抓住它。您的计算机,即您的应用 运行 所在的本地环境,被视为可靠的媒介。因此,NSTask 被设计为期望你提供给它的任何路径都保证存在。这很好,因为人们通常使用 NSTask 来启动标准系统可执行文件(bash
、diff
、rsync
等)。路径错误的崩溃旨在帮助您轻松找到代码中的错误。如果您要启动自己的 custom-built 嵌入应用程序包中的二进制文件,您应该 真的 改用 XPC。
如果您确实需要使用 NSTask 来启动不可靠的路径,那么在创建对象之前,您需要使用 NSFileManager 的 fileExistsAtPath(_:isDirectory:)
手动验证路径并做出相应的反应。如果连 POSIX 权限标志都不可靠(此时,您的应用程序可能存在一些严重的安全问题;如果这是一个消费者应用程序项目,我建议您重新考虑您的设计),您还需要检查文件的 NSFilePosixPermissions
属性以确保它是可执行的。
在 Mac OS X High Sierra 中,launch()
已弃用。
您可以使用 run()
代替:
let process = Process()
// ...
do {
process.run()
} catch let error as NSError {
print(error.localizedDescription)
// ...
}
另请参阅 Apple Dev Docs