Native Process - Flex Adobe Integrated Runtime (AIR)

Adobe AIR supports running Native Processes from within Flash Player. That means any other program in the Operating system can be executed, as well as controlled from the AIR application. Creating an AIR application is very simple, if you have FlashDevelop.  Go to Project->New Project->Flex AIR Projector->Open, Run the CreateCertificate.bat for creating a Certificate for your own and done.

Before starting the Application, atleast we can check for the Native Process support [of course we should]. Thought of a simple generic logic that works out for the pre-check of support, like as every App does, if no support then exit. The code is as follows

import flash.desktop.NativeProcess;
import flash.desktop.NativeApplication;

import flash.desktop.NativeProcess;
import flash.desktop.NativeApplication;

public function check_support():void
{
    if (!NativeProcess.isSupported) {
        Alert.show(
        "Native process not Supported"
        "Depencency Check"
        Alert.OK, 
        this, 
        exit_app);
}
}

public function exit_app(event:CloseEvent):void
{
    NativeApplication.nativeApplication.exit();
}

Native Process support can be added by modifying the application.xml file. The following field has to added to that for supporting Native Process.

<supportedProfiles>extendedDesktop</supportedProfiles>

A detailed article on Flex Alert can be found here. So, now, lets assume the NativeProcess is supported. Lets take a look into setting up the NativeProcess before being executed. There are few classes to be imported. They are

import ArgumentError;
import mx.controls.Alert;
import flash.filesystem.File;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.errors.IllegalOperationError;
import flash.events.NativeProcessExitEvent;
import flash.desktop.NativeProcessStartupInfo;

Create an instance of the NativeProcess class

var process = new NativeProcess();

Add Event Listeners

The following events could be useful at all situations of the application.

Exit Event - Can get the Exit code of the process just being executed


process.addEventListener(NativeProcessExitEvent.EXIT, trace_exit_code);

private function trace_exit_code(event:NativeProcessExitEvent):void
{
    exit_code = event.exitCode;
}

Exit codes are useful when some dependency is there on the running process to be executed successfully. Further logic can be coded based on the exit code of the process or just to alert the user about the execution of the process succeeded or failed.

Standard output redirection - Get the text output to stdout and stderr

var stdout:String = new String();
var stderr:String = new String();

process.addEventListener(ProgressEvent.STANDARD_ERROR_DATA,  grab_stderr);

private function grab_stderr(event:ProgressEvent):void
{
    stderr += process.standardOutput.readUTFBytes(
              process.standardOutput.bytesAvailable);
}

process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, grab_stdout);

private function grab_stdout(event:ProgressEvent):void
{
    stdout += process.standardOutput.readUTFBytes(
              process.standardOutput.bytesAvailable);
}

Now, when the process completes, stdout and stderr contain the output of the program [to the standard consoles]. This would be helpful in automating simple programs, especially a command line program. For example, a simple AIR application can be created that uses NativeProcess class to run the System-info program and obtain the output using the above mentioned functions and display it in a more Graphical way.

IO Error


process.addEventListener(IOErrorEvent.STANDARD_ERROR_IO_ERROR,  trace_io_error);
process.addEventListener(IOErrorEvent.STANDARD_OUTPUT_IO_ERROR, trace_io_error);

private function trace_io_error(event:IOErrorEvent):void
{
    exit_code = some_exit_code;
}

This indicates an IO error happened during a write to standard consoles.

Create a File object for the executable.

var file_obj:File = new File("some.exe");

Check if the executable exists

if (!file_obj.exists) {
   exit_code = some_error_code;
}

Set up the NativeProcessStartupInfo.

var process_info:NativeProcessStartupInfo = new NativeProcessStartupInfo();
var argv= new Vector.<String>();
argv.push("arg1");

Only two things are needed, the arguments passed to the executable, and a File object of the executable.

process_info.arguments = argv;
process_info.executable = file_obj;

Start the process,

try {
    process.start(process_info);
} catch (error:IllegalOperationError) {
    exit_code = some_error_code;
} catch (error:ArgumentError) {
    exit_code = some_error_code;
} catch (error:Error) {
    exit_code = some_error_code;
}

And if everything goes well, the process would have been up and running. But, how can someone see if a process is completed or not. There are other methods, but the simple one could be checking repeatedly at frequent intervals. I have used a local variable for the running status of the process. Once the process starts, running should be true and of course, upon exit it should be false.

The code is added at the following parts

try {
    process.start(process_info);
    running = true;
}

and,

private function trace_exit_code(event:NativeProcessExitEvent):void
{
    exit_code = event.exitCode;
    running = false;
}

And for checking, just implement a simple Timer.

t = new Timer(100, 0);
t.addEventListener(TimerEvent.TIMER, check_status);
t.start();

public function check_status(event:TimerEvent):void
{
    if (running == false) {
        t.stop();
    }
}

That is all. Now the process will be executed as well as the other things like output, error codes, exceptions etc can also be inspected. 

Thanks for reading.


See also 

1 comment: