Я пишу быстрое приложение для MacOSX. Это приложение использует Process для запуска большого количества скриптов, таких как shell 、 ruby 、 python.Когда приложение получит что-то из скрипта на выводе standerd, оно отобразится в приложении.пользователь делает что-то на основе того, что показывают в приложении.Затем приложение использует входные данные и отправляет их в сценарий.Процесс, описанный выше, может быть подан при запуске сценария.
Код, который я пишу, работает, но только для сценария оболочки.При запуске 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
}
}