Communicating with native processes in AIR
As of Adobe AIR 2, AIR applications can run and communicate with other native processes via the command line. For example, an AIR application can run a process and communicate with it via the standard input and output streams.
To communicate with native processes, package an AIR application to be installed via a native installer. The file type of native installer is specific to the operating system for which it is created:
It is a DMG file on Mac OS.
It is an EXE file on Windows.
It is an RPM or DEB package on Linux.
These applications are known as extended desktop profile applications. You can
create a native installer file by specifying the -target native
option when
calling the -package
command using ADT.
Overview of native process communications
An AIR application in the extended desktop profile can execute a file, as if it were invoked by the command line. It can communicate with the standard streams of the native process. Standard streams include the standard input stream (stdin), the output stream (stdout), the standard error stream (stderr).
Note: Applications in the extended desktop profile can also launch files and
applications using the File.openWithDefaultApplication()
method. However,
using this method does not provide the AIR application with access to the
standard streams. For more information, see
Opening files with the default system application
The following code sample shows how to launch a test.exe application in the
application directory. The application passes the argument "hello"
as a
command-line argument, and it adds an event listener to the process's standard
output stream:
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);
}
Launching and closing a native process
To launch a native process, set up a NativeProcessInfo object to do the following:
Point to the file you want to launch
Store command-line arguments to pass to the process when launched (optional)
Set the working directory of the process (optional)
To start the native process, pass the NativeProcessInfo object as the parameter
of the start()
method of a NativeProcess object.
For example, the following code shows how to launch a test.exe application in
the application directory. The application passes the argument "hello"
and
sets the user's documents directory as the working directory:
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);
To terminate the process, call the exit()
method of the NativeProcess object.
If you want a file to be executable in your installed application, make sure that it's executable on the file system when you package your application. (On Mac and Linux, you can use chmod to set the executable flag, if needed.)
Communicating with a native process
Once an AIR application has started a native process, it can communicate with the standard input, standard output, and standard error streams of the process.
You read and write data to the streams using the following properties of the NativeProcess object:
standardInput
—Contains access to the standard input stream data.standardOutput
—Contains access to the standard output stream data.standardError
—Contains access to the standard error stream data.
Writing to the standard input stream
You can write data to the standard input stream using the write methods of the
standardInput
property of the NativeProcess object. As the AIR application
writes data to the process, the NativeProcess object dispatches
standardInputProgress
events.
If an error occurs in writing to the standard input stream, the NativeProcess
object dispatches an ioErrorStandardInput
event.
You can close the input stream by calling the closeInput()
method of the
NativeProcess object. When the input stream closes, the NativeProcess object
dispatches a standardInputClose
event.
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();
}
Reading from the standard output stream
You can read data from the standard output stream using the read methods of this
property. As the AIR application gets output stream data from the process, the
NativeProcess object dispatches standardOutputData
events.
If an error occurs in writing to the standard output stream, the NativeProcess
object dispatches a standardOutputError
event.
When process closes the output stream, the NativeProcess object dispatches a
standardOutputClose
event.
When reading data from the standard input stream, be sure to read data as it is
generated. In other words, add an event listener for the standardOutputData
event. In the standardOutputData
event listener, read the data from the
standardOutput
property of the NativeProcess object. Do not simply wait for
the standardOutputClose
event or the exit
event to read all data. If you do
not read data as the native process generates the data, the buffer can fill up,
or data can be lost. A full buffer can cause the native process to stall when
trying to write more data. However, if you do not register an event listener for
the standardOutputData
event, then the buffer will not fill and the process
will not stall. In this case, you will not have access to the data.
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);
}
Reading from the standard error stream
You can read data from the standard error stream using the read methods of this
property. As the AIR application reads error stream data from the process, the
NativeProcess object dispatches standardErrorData
events.
If an error occurs in writing to the standard error stream, the NativeProcess
object dispatches an standardErrorIoError
event.
When process closes the error stream, the NativeProcess object dispatches a
standardErrorClose
event.
When reading data from the standard error stream, be sure to read data as it is
generated. In other words, add an event listener for the standardErrorData
event. In the standardErrorData
event listener, read the data from the
standardError
property of the NativeProcess object. Do not simply wait for the
standardErrorClose
event or the exit
event to read all data. If you do not
read data as the native process generates the data, the buffer can fill up, or
data can be lost. A full buffer can cause the native process to stall when
trying to write more data. However, if you do not register an event listener for
the standardErrorData
event, then the buffer will not fill and the process
will not stall. In this case, you will not have access to the data.
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);
}
Security considerations for native process communication
The native process API can run any executable on the user's system. Take extreme care when constructing and executing commands. If any part of a command to be executed originates from an external source, carefully validate that the command is safe to execute. Likewise, your AIR application should validate any data passed to a running process.
However, validating input can be difficult. To avoid such difficulties, it is best to write a native application (such as an EXE file on Windows) that has specific APIs. These APIs should process only those commands defined by the application. For example, the application may accept only a limited set of instructions via the standard input stream.
AIR on Windows does not allow you to run .bat files directly. The command
interpreter application (cmd.exe) executes Windows .bat files. When you invoke a
.bat file, this command application can interpret arguments passed to the
command as additional applications to launch. A malicious injection of extra
characters in the argument string could cause cmd.exe to execute a harmful or
insecure application. For example, without proper data validation, your AIR
application may call myBat.bat myArguments c:/evil.exe
. The command
application would launch the evil.exe application in addition to running your
batch file.
More Help topics
Packaging an AIR application in a native installer