我编写了一个快速的MacOSX App。该App使用Process来启动许多脚本,例如shell,ruby,python。 当应用程序获得脚本输出的标准输出内容时,它将显示在应用程序上。用户根据应用程序上显示的内容进行操作。然后,应用获取使用输入,并将该输入发送到脚本中。 脚本运行时,上面的过程可能是服务时间。
我编写的代码有效,但仅适用于shell脚本。启动ruby,python时,该应用无法获取脚本输出。
这样的脚本文件
# test.sh in my project
echo ~
read inputIn
echo "$inputIn"
read inputInOUt
mkDir "$inputInOUt"
# testruby.rb in my project
print "please input your name"
name=gets.chomp
puts "please input your age"
age=gets.chomp
# testpyton.pyt in my project
import sys
print "please input your name"
name=sys.stdin.readline()
print "please input your age"
age=sys.stdin.readline()
# work
testInteract = EBInteract()
testInteract?.excutScript("/Users/XXXXX/Library/Developer/Xcode/DerivedData/EasyBox-fmazpncoeyhnkgddokkilcbsebby/Build/Products/Debug/EasyBox.app/Contents/Resources/test.sh", "test_shell")
# can not work
// testInteract = EBInteract()
// testInteract?.excutScript("/Users/XXXXX/Library/Developer/Xcode/DerivedData/EasyBox-fmazpncoeyhnkgddokkilcbsebby/Build/Products/Debug/EasyBox.app/Contents/Resources/testruby.rb")
# can not work
// testInteract = EBInteract()
// testInteract?.excutScript("/Users/XXXXX/Library/Developer/Xcode/DerivedData/EasyBox-fmazpncoeyhnkgddokkilcbsebby/Build/Products/Debug/EasyBox.app/Contents/Resources/testpython.py")
import Foundation
/*
* 该类负责与脚本交互
*/
class EBInteract {
var times: Int = 1
func excutScript(_ parameter: String...) -> Bool {
guard parameter.count > 0 else {
return false
}
let task = Process()
let scriptFilePath = parameter[0]
switch scriptFilePath {
case _ where scriptFilePath.hasSuffix(".py"):
task.launchPath = "/usr/local/bin/python"
case _ where scriptFilePath.hasSuffix(".rb"):
task.launchPath = "/Users/wangwenjun04/.rvm/rubies/ruby-2.4.1/bin/ruby"
// task.launchPath = "/bin/bash"
default:
task.launchPath = "/bin/bash"
}
task.arguments = parameter
let standardOutput = Pipe()
task.standardOutput = standardOutput
standardOutput.fileHandleForReading.waitForDataInBackgroundAndNotify()
let standardInput = Pipe()
task.standardInput = standardInput;
// standardInput.fileHandleForWriting.readInBackgroundAndNotify()
// standardInput.fileHandleForWriting.waitForDataInBackgroundAndNotify()
// let fh = FileHandle(forWritingAtPath:"/Users/wangwenjun04/Library/Developer/Xcode/DerivedData/EasyBox-fmazpncoeyhnkgddokkilcbsebby/Build/Products/Debug/EasyBox.app/Contents/Resources/input.txt")
// task.standardInput = fh
// dup2(fh!.fileDescriptor, STDIN_FILENO)
var dataObserver: NSObjectProtocol!
dataObserver = NotificationCenter.default.addObserver(forName: Notification.Name.NSFileHandleDataAvailable,
object: standardOutput.fileHandleForReading, queue: OperationQueue.main, using: {notification in
if let output = notification.object as? FileHandle {
let data = output.availableData
guard data.count > 0 else {
NotificationCenter.default.removeObserver(dataObserver)
return
}
let outPutInfo: String? = String(data: data, encoding: String.Encoding.utf8)
print("output info is \(outPutInfo ?? "nothing")")
if self.times == 1 {
if let input = task.standardInput as? Pipe {
var info1 = "wwj-wwj\n"
input.fileHandleForWriting.write(info1.data(using: String.Encoding.utf8)!)
// input.synchronizeFile()
}
self.times += 1
}
else {
if let input = task.standardInput as? Pipe {
var info1 = "wwj-18\n"
input.fileHandleForWriting.write(info1.data(using: String.Encoding.utf8)!)
// input.synchronizeFile()
}
}
standardOutput.fileHandleForReading.waitForDataInBackgroundAndNotify()
}
})
task.launch()
// task.waitUntilExit()
return true
}
}