首页 > 解决方案 > 在未完成的情况下从应用程序获取标准输出

问题描述

我有这个用 shell 脚本运行的游戏。游戏在终端运行时,会主动打印“连接到服务器”或“断开连接”等信息。

const app = Application.currentApplication()
app.includeStandardAdditions = true

const terminalOutput = app.doShellScript('pathToGame');
console.log(terminalOutput);

此代码仅在应用程序停止/退出时打印出来。只打印最后一条语句。我试图找到一种方法来打印每条语句。无论是在日志文件中还是作为返回值,它都会在进程运行时打印一些内容,而无需停止/退出它。

01:21:22: Application Running
01:21:23: Request connection to "ip address"
01:21:24: Connected to server "ip address"
01:45:01: Disconnected from server "ip address"
//Here my script would detect and try to log in again

例如:我打开游戏。游戏打印“应用程序正在运行”,现在有了该值,我知道游戏已打开,我可以告诉我的脚本登录。然后,如果游戏以某种方式打印“与服务器断开连接”,我的应用程序将检测到该标准输出并将下降进入它将尝试再次登录的功能。

在应用程序仍在运行时获取标准输出是可能的吗?

标签: macosjavascript-automation

解决方案


仅使用普通的 JXA 这样做是不可能的,因为这样做doShellScript有些非常有限。

仍然可以利用 Objective-C 桥实现完整的流程执行。以下是我如何在项目中将命令作为子进程执行以获取附加的终端列。

// Import `Foundation` to be able use `NSTask`.
ObjC.import('Foundation');

// Launch `NSTask` `tput cols` to get number of cols.
const { pipe } = $.NSPipe;
const file = pipe.fileHandleForReading;
const task = $.NSTask.alloc.init;

task.launchPath = '/bin/sh';
task.arguments = ['-c', 'tput cols'];
task.standardOutput = pipe;

task.launch; // Run the task.

let data = file.readDataToEndOfFile; // Read the task's output.
file.closeFile;

// Parse the task's output.
data = $.NSString.alloc.initWithDataEncoding(data, $.NSUTF8StringEncoding);
const result = ObjC.unwrap(data); // Unwrap `NSString`.
return parseInt(result, 10);

对于您的情况,请查看https://developer.apple.com/documentation/foundation/pipe/1414352-filehandleforreading以查看有关如何从pipe.fileHandleForReading.

以下是我的示例解决方案,尽管它尚未经过测试。

// Import `Foundation` to be able use `NSTask`.
ObjC.import('Foundation');

// Launch `NSTask`.
const { pipe } = $.NSPipe;
const file = pipe.fileHandleForReading;
const task = $.NSTask.alloc.init;

task.launchPath = '/bin/sh';
task.arguments = ['-c', 'pathToYourGame'];
task.standardOutput = pipe;

task.launch; // Run the task.

let data;
for(;;) {
  data = file.availableData; // Read the task's output.
  if(!data) {
    file.closeFile;
    break;
  }

  // Parse the task's output.
  data = $.NSString.alloc.initWithDataEncoding(data, $.NSUTF8StringEncoding);
  const result = ObjC.unwrap(data);

  // Process your streaming data.
  doSomething(result);
}

推荐阅读