与 AIR 中的本机进程通信

Adobe AIR 2 和更高版本

自 Adobe AIR 2 起,AIR 应用程序可以通过命令行运行并与其他本机进程通信。例如,AIR 应用程序可以运行进程,并通过标准的输入和输出流与之通信。

要与本机进程通信,请将 AIR 应用程序打包为通过本机安装程序安装。本机安装程序的文件类型取决于目标操作系统:

  • 在 Mac OS 中为 DMG 文件。

  • 在 Windows 中为 EXE 文件。

  • 在 Linux 中为 RPM 或 DEB 包。

这些应用程序称为扩展的桌面配置文件应用程序。可以通过在使用 ADT 调用 -package 命令时指定 -target native 选项来创建本机安装程序文件。

本机进程通信概述

扩展的桌面配置文件中的 AIR 应用程序可以执行文件,执行方式与命令行调用该文件的方式相同。它可以与本机进程的标准流通信。标准流包括标准输入流 (stdin)、输出流 (stdout) 和标准错误流 (stderr)。

注: 扩展的桌面配置文件中的应用程序还可以使用 File.openWithDefaultApplication() 方法启动文件和应用程序。然而,使用此方法不能为 AIR 应用程序提供访问标准流的权限。有关详细信息,请参阅 使用默认系统应用程序打开文件

以下代码示例显示如何启动应用程序目录中的 test.exe 应用程序。应用程序将参数 "hello" 作为命令行参数传递,并将事件侦听器添加到进程的标准输出流中:

var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo(); 
var file:File = File.applicationDirectory.resolvePath("test.exe"); 
nativeProcessStartupInfo.executable = file; 
var processArgs:Vector.<String> = new Vector.<String>(); 
processArgs.push("hello"); 
nativeProcessStartupInfo.arguments = processArgs; 
process = new NativeProcess(); 
process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onOutputData); 
process.start(nativeProcessStartupInfo); 
public function onOutputData(event:ProgressEvent):void 
{ 
    var stdOut:ByteArray = process.standardOutput; 
    var data:String = stdOut.readUTFBytes(process.standardOutput.bytesAvailable); 
    trace("Got: ", data); 
}

启动和关闭本机进程

要启动本机进程,请设置 NativeProcessInfo 对象以执行下列操作:

  • 指向您要启动的文件

  • 存储命令行参数以在启动时传递到进程 (optional)

  • 设置进程的工作目录(可选)

若要开始本机进程,请将 NativeProcessInfo 对象作为 NativeProcess 对象的 start() 方法的参数进行传递。

例如,以下代码显示如何启动应用程序目录中的 test.exe 应用程序。应用程序传递参数 "hello" ,并将用户的文档目录设置为工作目录:

var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo(); 
var file:File = File.applicationDirectory.resolvePath("test.exe"); 
nativeProcessStartupInfo.executable = file; 
var processArgs:Vector.<String> = new Vector.<String>(); 
processArgs[0] = "hello"; 
nativeProcessStartupInfo.arguments = processArgs; 
nativeProcessStartupInfo.workingDirectory = File.documentsDirectory; 
process = new NativeProcess(); 
process.start(nativeProcessStartupInfo); 

若要终止进程,可调用 NativeProcess 对象的 exit() 方法。

如果希望可以在已安装应用程序中执行某个文件,请确保在您打包应用程序时,该文件在文件系统中是可执行文件。(在 Mac 和 Linux 上,如果需要,可以使用 chmod 来设置可执行标记。)

与本机进程通信

一旦 AIR 应用程序启动本机进程后,它就可以与该进程的标准输入、标准输出和标准错误流通信。

使用 NativeProcess 对象的下列属性流读取数据以及将数据写入流:

  • standardInput — 包含访问标准输入流数据的权限。

  • standardOutput — 包含对标准输出流数据的访问。

  • standardError — 包含访问标准错误流数据的权限。

写入标准输入流

您可以使用 NativeProcess 对象的 standardInput 属性的写入方法将数据写入标准输入流。AIR 应用程序将数据写入进程时,NativeProcess 对象会调度多个 standardInputProgress 事件。

如果写入标准输入流时出错,NativeProcess 对象会调度 ioErrorStandardInput 事件。

可以通过调用 NativeProcess 对象的 closeInput() 方法关闭输入流。关闭输入流后,NativeProcess 对象会调度一个 standardInputClose 事件。

var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo(); 
var file:File = File.applicationDirectory.resolvePath("test.exe"); 
nativeProcessStartupInfo.executable = file; 
process = new NativeProcess(); 
process.start(nativeProcessStartupInfo); 
process.standardInput.writeUTF("foo"); 
if(process.running) 
{ 
    process.closeInput(); 
}

从标准输出流中读取

可使用此属性的读取方法从标准输出流中读取数据。AIR 应用程序从进程获取输出流数据时,NativeProcess 对象会调度多个 standardOutputData 事件。

如果写入标准输出流时出错,NativeProcess 对象会调度一个 standardOutputError 事件。

当进程关闭输出流时,NativeProcess 对象会调度 standardOutputClose 事件。

从标准输入流读取数据时,请确保在生成数据时读取数据。换句话说,为 standardOutputData 事件添加事件侦听器。在 standardOutputData 事件侦听器中,从 NativeProcess 对象的 standardOutput 属性读取数据。不要只等待 standardOutputClose 事件或 exit 事件读取所有数据。如果在本机进程生成数据时不读取数据,可能导致缓冲区填满或数据丢失。缓冲区填满可能会导致本机进程在尝试写入更多数据时终止。但是,如果您不为 standardOutputData 事件注册事件侦听器,则不会填充缓冲区,也不会终止进程。在这种情况下,您将无权访问数据。

var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo(); 
var file:File = File.applicationDirectory.resolvePath("test.exe"); 
nativeProcessStartupInfo.executable = file; 
process = new NativeProcess(); 
process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, dataHandler); 
process.start(nativeProcessStartupInfo); 
var bytes:ByteArray = new ByteArray(); 
function dataHandler(event:ProgressEvent):void 
{ 
    bytes.writeBytes(process.standardOutput.readBytes(process.standardOutput.bytesAvailable); 
}

从标准错误流中读取

可使用此属性的读取方法从标准错误流中读取数据。AIR 应用程序从进程中读取错误流数据时,NativeProcess 对象会调度多个 standardErrorData 事件。

如果写入标准错误流时出错,NativeProcess 对象会调度一个 standardErrorIoError 事件。

当进程关闭错误流时,NativeProcess 对象会调度 standardErrorClose 事件。

从标准错误流中读取数据时,请确保在生成数据时读取数据。换句话说,为 standardErrorData 事件添加事件侦听器。在 standardErrorData 事件侦听器中,从 NativeProcess 对象的 standardError 属性中读取数据。不要只等待 standardErrorClose 事件或 exit 事件读取所有数据。如果在本机进程生成数据时不读取数据,可能导致缓冲区填满或数据丢失。缓冲区填满可能会导致本机进程在尝试写入更多数据时终止。但是,如果您不为 standardErrorData 事件注册事件侦听器,则不会填充缓冲区,也不会终止进程。在这种情况下,您将无权访问数据。

var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo(); 
var file:File = File.applicationDirectory.resolvePath("test.exe"); 
nativeProcessStartupInfo.executable = file; 
process = new NativeProcess(); 
process.addEventListener(ProgressEvent.STANDARD_ERROR_DATA, errorDataHandler); 
process.start(nativeProcessStartupInfo); 
var errorBytes:ByteArray = new ByteArray(); 
function errorDataHandler(event:ProgressEvent):void 
{ 
    bytes.writeBytes(process.standardError.readBytes(process.standardError.bytesAvailable); 
}

本机进程通信的安全性注意事项

本机进程 API 可以在用户系统上运行任何可执行文件。构造和执行命令时要格外小心。如果要执行的命令的任何部分来自外部源,务必仔细验证该命令可以安全执行。同样,AIR 应用程序应对传递给正在运行的进程的任何数据进行验证。

但是,对输入进行验证可能十分困难。为了避免这种困难,最好编写具有特定 API 的本机应用程序(如 Windows 上的 EXE 文件)。这些 API 应该只处理由应用程序定义的那些命令。例如,应用程序可能只通过标准输入流接受有限的一组指令。

Windows 上的 AIR 不允许直接运行 .bat 文件。命令解释器应用程序 (cmd.exe) 执行 Windows .bat 文件。调用 .bat 文件时,此命令应用程序可以将传递给该命令的参数解释为要启动的其他应用程序。在参数字符串中恶意注入额外字符可能导致 cmd.exe 执行有害的或不安全的应用程序。例如,在没有经过正确的数据验证的情况下,AIR 应用程序可能会调用 myBat.bat myArguments c:/evil.exe 。该命令应用程序除了运行您的批处理文件外,还将启动 evil.exe 应用程序。