Comunicación con procesos nativos en AIR

Adobe AIR 2 y posterior

Tal y como sucede con Adobe AIR 2, las aplicaciones de AIR se pueden ejecutar y comunicarse con otros procesos nativos mediante la línea de comandos. Por ejemplo, una aplicación de AIR puede ejecutar un proceso y comunicarse con él a través de los flujos de entrada y salida.

Para comunicarse con procesos nativos, empaquete una aplicación de AIR para que se instale a través de un archivo de instalación nativo. El tipo de archivo de instalación nativo es específico del sistema operativo para el cual se crea:

  • En Mac OS es un archivo DMG.

  • En Windows es un archivo EXE.

  • En Linux es un paquete RPM o DEB.

Estas aplicaciones se conocen como aplicaciones de perfil de escritorio ampliado. Un archivo de instalación nativo se puede crear especificando la opción -target native al llamar al comando -package con el uso de ADT.

Información general sobre las comunicaciones de proceso nativo

Una aplicación de AIR del perfil de escritorio ampliado puede ejecutar un archivo como si se invocase desde la línea de comandos. Se puede comunicar con los flujos estándar del proceso nativo. Entre los flujos estándar se incluyen el flujo de entrada estándar (stdin), el flujo de salida (stdout) y el flujo de error estándar (stderr).

Nota: las aplicaciones del perfil de escritorio ampliado también pueden iniciar archivos y aplicaciones utilizando el método File.openWithDefaultApplication() . Sin embargo, el uso de este método no proporciona a la aplicación de AIR acceso a los flujos estándar. Para obtener más información, consulte Apertura de archivos con la aplicación del sistema predeterminada

En el siguiente ejemplo de código se muestra cómo iniciar una aplicación test.exe en el directorio de la aplicación. La aplicación transmite "hello" como argumento de la línea de comandos y añade un detector de eventos al flujo de salida estándar del proceso:

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); 
}

Inicio y cierre de un proceso nativo

Para iniciar un proceso nativo, configure un objeto NativeProcessInfo para que realice lo siguiente:

  • Seleccione el archivo que desee iniciar.

  • Almacene argumentos de la línea de comandos para transmitir el proceso cuando se inicie. (opcional)

  • Establezca el directorio de trabajo del proceso (opcional)

Para iniciar el proceso nativo, transmita el objeto NativeProcessInfo como parámetro del método start() de un objeto NativeProcess.

Por ejemplo, el siguiente código muestra cómo iniciar una aplicación test.exe en el directorio de la aplicación. La aplicación transmite el argumento "hello" y establece el directorio de documentos del usuario como directorio de trabajo:

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); 

Para terminar el proceso, llame al método exit() del objeto NativeProcess.

Si quiere que un archivo sea ejecutable en su aplicación instalada, asegúrese de que lo es en el sistema de archivos en el momento de empaquetar la aplicación. (En Mac y Linux, puede utilizar chmod para establecer el indicador de ejecutable, si es necesario.)

Comunicación con un proceso nativo

Una vez que una aplicación de AIR se ha iniciado como proceso nativo, puede comunicarse con los flujos de error y de entrada y salida estándar del proceso.

Los datos se leen y se escriben en los flujos utilizando las siguientes propiedades del objeto NativeProcess:

  • standardInput : contiene acceso a los datos del flujo de entrada estándar.

  • standardOutput : contiene acceso a los datos del flujo de salida estándar.

  • standardError : contiene acceso a los datos del flujo de error estándar.

Escritura en el flujo de entrada estándar

Los datos se pueden escribir en el flujo de entrada estándar utilizando los métodos de escritura de la propiedad standardInput del objeto NativeProcess. A medida que la aplicación de AIR escribe datos en el proceso, el objeto NativeProcess distribuye eventos standardInputProgress .

Si se produce un error al escribir en el flujo de entrada estándar, el objeto NativeProcess distribuye un evento ioErrorStandardInput .

El flujo de entrada se puede cerrar llamando al método closeInput() del objeto NativeProcess. Cuando el flujo de entrada se cierra, el objeto NativeProcess distribuye un evento 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(); 
}

Lectura en el flujo de salida estándar

Los datos se pueden leer en el flujo de salida estándar utilizando los métodos de lectura de esta propiedad. A medida que la aplicación de AIR obtiene datos del flujo de salida del proceso, el objeto NativeProcess distribuye eventos standardOutputData .

Si se produce un error al escribir en el flujo de salida estándar, el objeto NativeProcess distribuye un evento standardOutputError .

Cuando el proceso cierra el flujo de salida, el objeto NativeProcess distribuye el evento standardOutputClose .

Cuando se leen datos del flujo de entrada estándar, es muy importante leerlos a medida que se generan. Dicho de otro modo, añada un detector de eventos para el evento standardOutputData . En el detector de eventos standardOutputData , lea los datos de la propiedad standardOutput del objeto NativeProcess. No se limite a esperar a que el evento standardOutputClose o exit lea todos los datos. Si no lee los datos a medida que el proceso nativo los genera, el búfer podría llenarse y los datos podrían perderse. Un búfer lleno puede provocar que el proceso nativo se bloquee al intentar escribir más datos. Sin embargo, si no registra un detector de eventos para el evento standardOutputData , el búfer no se llenará y el proceso no se bloqueará. En ese caso, no podrá acceder a los datos.

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); 
}

Lectura del flujo de error estándar

Los datos se pueden leer en el flujo de error estándar utilizando los métodos de lectura de esta propiedad. A medida que la aplicación de AIR lee los datos del flujo de error del proceso, el objeto NativeProcess distribuye eventos standardErrorData .

Si se produce un error al escribir en el flujo de error estándar, el objeto NativeProcess distribuye un evento standardErrorIoError .

Cuando el proceso cierra el flujo de error, el objeto NativeProcess distribuye un evento standardErrorClose ..

Cuando se leen datos del flujo de error estándar, es muy importante leerlos a medida que se generan. Dicho de otro modo, añada un detector de eventos para el evento standardErrorData . En el detector de eventos standardErrorData , lea los datos de la propiedad standardError del objeto NativeProcess. No se limite a esperar a que el evento standardErrorClose o exit lea todos los datos. Si no lee los datos a medida que el proceso nativo los genera, el búfer podría llenarse y los datos podrían perderse. Un búfer lleno puede provocar que el proceso nativo se bloquee al intentar escribir más datos. Sin embargo, si no registra un detector de eventos para el evento standardErrorData , el búfer no se llenará y el proceso no se bloqueará. En ese caso, no podrá acceder a los datos.

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); 
}

Seguridad en la comunicación del proceso nativo

La API del proceso nativo puede ejecutar cualquier ejecutable en el sistema del usuario. Debe tener mucho cuidado al construir y ejecutar comandos. Si algún fragmento de un comando que se ejecuta viene desde un origen externo, compruebe atentamente que es seguro ejecutar dicho comando. Asimismo, la aplicación de AIR debe validar datos transferidos a un proceso en ejecución.

Sin embargo, validar los datos entrantes puede resultar difícil. Para evitar esta dificultad, es mejor escribir una aplicación nativa (como un archivo EXE en Windows) con API específicas. Estas API deben procesar solo dichos comandos definidos por la aplicación. Por ejemplo, la aplicación solo puede aceptar una serie limitada de instrucciones a través de la secuencia de entrada estándar.

En Windows, AIR no le permite ejecutar archivos .bat directamente. La aplicación del interpretador de comandos (cmd.exe) ejecuta archivos .bat de Windows. Cuando se invoca un archivo .bat, esta aplicación de comandos puede interpretar argumentos que se transfieren al comando como aplicaciones adicionales para iniciar. La presencia maliciosa de caracteres adicionales en la cadena del argumento puede provocar que un cmd.exe ejecute una aplicación insegura o dañina. Por ejemplo, sin una validación adecuada de datos, la aplicación de AIR puede llamar a myBat.bat myArguments c:/diablo.exe . La aplicación de comandos iniciaría la aplicación diablo.exe además de ejecutar el archivo por lotes.