Comunicação com processos nativos do AIR

Adobe AIR 2 e posterior

Como o Adobe AIR 2, os aplicativos AIR podem executar e se comunicar com outros processos nativos por meio da linha de comando. Por exemplo, um aplicativo do AIR pode executar um processo e se comunicar com ele pode meio da entrada padrão e dos fluxos de saída.

Para se comunicar com processos nativos, empacote um aplicativo do AIR para ser instalado através de um instalador nativo. O tipo de arquivo do instalador nativo é específico do sistema operacional para o qual é criado:

  • É um arquivo DMG no Mac OS.

  • É um arquivo EXE no Windows.

  • É um pacote RPM ou DEB no Linux.

Esses aplicativos são conhecidos como aplicativos de perfil estendido de desktop. Você pode criar um arquivo do instalador nativo especificando a opção -target native ao chamar o comando -package usando ADT.

Visão geral das comunicações do processo nativo

Uma aplicativo do AIR no perfil estendido de desktop pode executar um arquivo, como se ele fosse chamado pela linha de comando. Ele pode se comunicar com os streams padrão do processo nativo. Os fluxos padrão incluem o fluxo de entrada padrão (stdin), o fluxo de saída (stdout) e o fluxo de erro padrão (stderr).

Nota: Os aplicativos no perfil estendido de desktop também podem abrir arquivos e aplicativos usando o método File.openWithDefaultApplication() . No entanto, usar este método não fornece ao aplicativo do AIR acesso aos fluxos padrão. Para obter mais informações, consulte Abertura de arquivos com o aplicativo padrão do sistema .

O exemplo de código a seguir mostra como abrir um aplicativo test.exe no diretório do aplicativo. O aplicativo passa o argumento "hello" como argumento da linha de comando, e acrescenta um ouvinte de evento ao fluxo de saída padrão do processo:

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

Abertura e fechamento de um processo nativo

Para abrir um processo nativo, configure um objeto NativeProcessInfo para fazer o seguinte:

  • Aponte para o arquivo que você deseja abrir

  • Armazene os argumentos da linha de comando a serem passados para o processo quando abertos (opcional)

  • Defina o diretório de trabalho do processo (opcional)

Para iniciar o processo nativo, passe o objeto NativeProcessInfo como parâmetro do método start() de um objeto NativeProcess.

Por exemplo, o código a seguir mostra como abrir um aplicativo test.exe no diretório do aplicativo. O aplicativo passa o argumento "hello" e define o diretório de documentos do usuário como diretório de trabalho:

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 encerrar o processo, chame o método exit() do objeto NativeProcess.

Se você desejar que um arquivo seja executável no aplicativo instalado, certifique-se de que ele é executável no sistema de arquivos, durante a criação do pacote do aplicativo. (No Mac e Linux, você pode utilizar o comando chmod para definir o indicador de executável, se necessário.)

Comunicação com um processo nativo

Depois que um aplicativo do AIR iniciar um processo nativo, ele pode se comunicar com os fluxos de entrada padrão, saída padrão e erro padrão do processo.

Você lê e grava os dados nos fluxos usando as seguintes propriedades do objeto NativeProcess:

  • standardInput — Contém acesso aos dados do fluxo de entrada padrão.

  • standardOutput — Contém acesso aos dados do fluxo de saída padrão.

  • standardError — Contém acesso aos dados do fluxo de erro padrão.

Gravação no fluxo de entrada padrão

Você pode gravar os dados no fluxo de entrada padrão usando os métodos de gravação da propriedade standardInput do objeto NativeProcess. Como o aplicativo do AIR grava os dados ao processo, o objeto NativeProcess despacha os eventos standardInputProgress .

Se ocorrer um erro na gravação para um fluxo de entrada padrão, o objeto NativeProcess envia um evento ioErrorStandardInput .

Você pode fechar o fluxo de entrada chamando o método closeInput() do objeto NativeProcess. Quando o fluxo de entrada se fecha, o objeto NativeProcess despacha o 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(); 
}

Leitura de um fluxo de saída padrão

Você pode ler os dados do fluxo de saída padrão usando os métodos de leitura desta propriedade. Como o aplicativo do AIR recebe os dados do fluxo de saída do processo, o objeto NativeProcess despacha os eventos standardOutputData .

Se ocorrer um erro ao gravar no fluxo de saída padrão, o objeto NativeProcess envia um evento standardOutputError .

Quando o processo fecha o fluxo de saída, o objeto NativeProcess envia um evento standardOutputClose .

Ao ler dados do stream de entrada padrão, certifique-se de ler os dados como eles são gerados. Em outras palavras, adicione um ouvinte de eventos para o evento standardOutputData . No ouvinte de eventos standardOutputData , leia os dados da propriedade standardOutput do objeto NativeProcess. Não fique apenas aguardando pelo evento standardOutputClose ou pelo evento exit para ler todos os dados. Caso você não leia os dados na medida em que o processo nativo os gera, o buffer pode encher ou dados podem ser perdidos. Um buffer cheio pode fazer com que o processo nativo pare quando estiver tentando escrever mais dados. No entanto, se você não registrar um ouvinte de eventos para o evento standardOutputData , o buffer não vai encher e o processo não vai parar. Neste caso, os dados não poderão ser acessados.

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

Leitura de um fluxo de erro padrão

Você pode ler os dados do fluxo de erro padrão usando os métodos de leitura desta propriedade. Como o aplicativo do AIR lê os dados de erros do fluxo de erro do processo, o objeto NativeProcess despacha os eventos standardErrorData .

Se ocorrer um erro ao gravar no fluxo de erro padrão, o objeto NativeProcess envia um evento standardErrorIoError .

Quando o processo fecha o fluxo de erros, o objeto NativeProcess envia um evento standardErrorClose ..

Ao ler dados do stream de erro padrão, certifique-se de ler os dados como eles são gerados. Em outras palavras, adicione um ouvinte de eventos para o evento standardErrorData . No ouvinte de eventos standardErrorData , leia os dados da propriedade standardError do objeto NativeProcess. Não fique apenas aguardando pelo evento standardErrorClose ou pelo evento exit para ler todos os dados. Caso você não leia os dados na medida em que o processo nativo os gera, o buffer pode encher ou dados podem ser perdidos. Um buffer cheio pode fazer com que o processo nativo pare quando estiver tentando escrever mais dados. No entanto, se você não registrar um ouvinte de eventos para o evento standardErrorData , o buffer não vai encher e o processo não vai parar. Neste caso, os dados não poderão ser acessados.

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

Considerações de segurança para a comunicação do processo nativo

A API de processo nativa pode executar qualquer executável no sistema do usuário. Seja muito cuidadoso ao construir e executar comandos. Se qualquer parte de um comando a ser executado tiver origem em uma fonte externa, valide cuidadosamente o comando para execução. Da mesma forma, o aplicativo do AIR deve validar quaisquer dados enviados para um processo em execução.

No entanto, a validação de entrada pode ser difícil. Para evitar problemas, o ideal é escrever um aplicativo nativo (ex: arquivo EXE do Windows) que possui a API específica. Estas APIs devem processar só aqueles comandos definidos pelo aplicativo. Por exemplo, o aplicativo pode aceitar somente um conjunto limitado de instruções por meio de fluxo de entrada padrão.

O AIR no Windows não permite que você execute arquivos do tipo .bat diretamente. O aplicativo interpretador de comandos (cmd.exe) executa os arquivos .bat do Windows. Ao chamar um arquivo .bat, este aplicativo de comando pode interpretar argumentos enviados ao comando como, por exemplo, aplicativos adicionais a serem executados. Uma injeção maliciosa de caracteres adicionais na string de argumento pode fazer com que o cmd.exe execute um aplicativo não seguro e que pode causar danos. Por exemplo, sem a validação apropriada de dados, seu aplicativo do AIR pode fazer uma chamada para myBat.bat myArguments c:/evil.exe . O aplicativo de comando iniciaria o aplicativo evil.exe além de executar o arquivo de lote.