Komunikacja z procesami rodzimymi w środowisku AIR

Adobe AIR 2 i starsze wersje

Począwszy od wersji 2 środowiska Adobe AIR aplikacje AIR mogą uruchamiać inne procesy rodzime i komunikować się z nimi za pośrednictwem wiersza poleceń. Aplikacja AIR może na przykład uruchomić proces i komunikować się z nim poprzez standardowe strumienie wejściowe i wyjściowe.

Aby możliwa była komunikacja z procesami rodzimymi, aplikacja AIR musi być przygotowana w formie pakietu instalowanego przez rodzimy program instalacyjny. Typ pliku rodzimego programu instalacyjnego jest właściwy dla systemu operacyjnego, dla którego został stworzony:

  • Jest to plik DMG w systemie Mac OS.

  • Jest to plik EXE w systemie Windows.

  • Jest to pakiet RPM lub DEB w systemie Linux.

Aplikacje takie nazywane są aplikacjami z rozszerzonym profilem lokalnym. Plik rodzimego programu instalacyjnego można utworzyć, podając opcję -target native w wywołaniu polecenia -package za pomocą środowiska ADT.

Przegląd komunikacji z procesami rodzimymi

Aplikacja AIR w rozszerzonym profilu aplikacji może uruchamiać plik w taki sposób, jakby został on wywołany z wiersza poleceń. Może również komunikować się ze standardowymi strumieniami procesu rodzimego. Strumienie standardowe to standardowy strumień wejściowy (stdin), standardowy strumień wyjściowy (stdout) i standardowy strumień błędów (stderr).

Uwaga: Aplikacje o rozszerzonym profilu lokalnym mogą również uruchamiać pliki i aplikacje za pomocą metody File.openWithDefaultApplication() . Jednak metoda ta nie zapewnia aplikacji AIR dostępu do strumieni standardowych. Więcej informacji zawiera sekcja Otwieranie plików za pomocą domyślnej aplikacji systemowej .

Następujący przykładowy kod ilustruje uruchomienie aplikacji test.exe w katalogu aplikacji. Aplikacja AIR przekazuje ciąg "hello" jako argument wiersza polecenia i dodaje detektor zdarzeń do standardowego strumienia wyjściowego procesu:

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

Uruchamianie i zamykanie procesu rodzimego

Aby uruchomić proces rodzimy, należy skonfigurować obiekt NativeProcessInfo w taki sposób, aby wykonał następujące działania:

  • Określił położenie pliku, który ma być uruchomiony.

  • Zapamiętał argumenty wiersza poleceń, jakie mają być przekazane do procesu w momencie uruchamiania go. (opcjonalnie)

  • Ustawia katalog roboczy procesu (opcjonalnie)

Aby uruchomić proces rodzimy, należy przekazać obiekt NativeProcessInfo jako parametr metody start() obiektu NativeProcess.

Poniższy przykładowy kod ilustruje uruchamianie aplikacji test.exe w katalogu aplikacji. Aplikacja AIR przekazuje argument "hello" i ustawia katalog dokumentów użytkownika jako katalog roboczy:

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

Aby zakończyć proces, należy wywołać metodę exit() obiektu NativeProcess.

Aby plik był plikiem wykonywalnym w zainstalowanej aplikacji, należy upewnić się, że jest on plikiem wykonywalnym w systemie plików przed utworzeniem pakietu aplikacji. (W systemach Mac i Linux można w razie potrzeby użyć polecenia chmod w celu ustawienia flagi pliku wykonywalnego).

Komunikacja z procesem rodzimym

Gdy aplikacja AIR uruchomi już proces rodzimy, może komunikować się ze standardowymi strumieniami procesu: wejściowym, wyjściowym i błędów.

Do zapisywania i odczytywania danych ze strumieni służą następujące właściwości obiektu NativeProcess:

  • standardInput — umożliwia dostęp do standardowego strumienia wejściowego.

  • standardOutput — umożliwia dostęp do standardowego strumienia wyjściowego.

  • standardError — umożliwia dostęp do standardowego strumienia błędów.

Zapis do standardowego strumienia wejściowego

Istnieje możliwość zapisywania danych do standardowego strumienia wejściowego przy użyciu metod udostępnianych przez właściwość standardInput obiektu NativeProcess. Gdy aplikacja AIR zapisuje dane do strumienia procesu, obiekt NativeProcess wywołuje zdarzenia standardInputProgress .

Jeśli podczas zapisywania do standardowego strumienia wejściowego wystąpi błąd, obiekt NativeProcess wywoła zdarzenie ioErrorStandardInput .

Strumień wejściowy można zamknąć, wywołując metodę closeInput() obiektu NativeProcess. Gdy strumień wejściowy jest zamykany, obiekt NativeProcess wywołuje zdarzenie 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(); 
}

Odczytywanie ze standardowego strumienia wyjściowego

Możliwe jest odczytywanie danych ze standardowego strumienia wyjściowego przy użyciu metod omawianej właściwości. W miarę, jak aplikacja AIR odbiera dane ze strumienia wyjściowego procesu, obiekt NativeProcess wywołuje zdarzenia standardOutputData .

Jeśli podczas zapisywania do standardowego strumienia wyjściowego wystąpi błąd, obiekt NativeProcess wywoła zdarzenie standardOutputError .

Gdy proces zamknie strumień wyjściowy, obiekt NativeProcess wywołuje zdarzenie standardOutputClose .

Podczas odczytu danych ze standardowego strumienia wejściowego należy pamiętać, by odczytywać dane w miarę, jak będą generowane. Innymi słowy, należy dodać detektor zdarzeń do zdarzenia standardOutputData. W detektorze zdarzeń standardOutputData należy odczytać dane z właściwości standardOutput obiektu NativeProcess. Nie wystarczy tylko czekać, aż zdarzenie standardOutputClose lub exit odczyta wszystkie dane. Jeżeli dane nie będą odczytywane równolegle z ich generowaniem przez proces rodzimy, może dojść do przepełnienia buforu i utraty danych. Pełny bufor może opóźnić działanie procesu rodzimego podczas próby zapisu większej ilości danych. Jednak jeżeli detektor zdarzeń nie zostanie zarejestrowany dla zdarzenia standardOutputData , wówczas bufor nie będzie się zapełniać, a proces będzie działać bez opóźnień. W takim przypadku nie będzie można uzyskać dostępu do danych.

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

Odczytywanie ze standardowego strumienia błędów

Możliwe jest odczytywanie danych ze standardowego strumienia błędów przy użyciu metod omawianej właściwości. W miarę, jak aplikacja AIR odbiera dane ze strumienia błędów procesu, obiekt NativeProcess wywołuje zdarzenia standardErrorData .

Jeśli podczas zapisywania do standardowego strumienia błędów wystąpi błąd, obiekt NativeProcess wywoła zdarzenie standardErrorIoError .

Gdy proces zamknie strumień błędów, obiekt NativeProcess wywołuje zdarzenie standardErrorClose ..

Podczas odczytu danych ze standardowego strumienia błędów należy pamiętać, by odczytywać dane w miarę, jak będą generowane. Innymi słowy, należy dodać detektor zdarzeń do zdarzenia standardErrorData . W detektorze zdarzeń standardErrorData należy odczytać dane z właściwości standardError obiektu NativeProcess. Nie wystarczy tylko czekać, aż zdarzenie standardErrorClose lub exit odczyta wszystkie dane. Jeżeli dane nie będą odczytywane równolegle z ich generowaniem przez proces rodzimy, może dojść do przepełnienia buforu i utraty danych. Pełny bufor może opóźnić działanie procesu rodzimego podczas próby zapisu większej ilości danych. Jednak jeżeli detektor zdarzeń nie zostanie zarejestrowany dla zdarzenia standardErrorData , wówczas bufor nie będzie się zapełniać, a proces będzie działać bez opóźnień. W takim przypadku dostęp do danych będzie niemożliwy.

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

Kwestie bezpieczeństwa w komunikacji z procesami rodzimymi

Za pomocą interfejsu API procesów rodzimych można uruchamiać dowolne pliki wykonywalne w systemie użytkownika. Konstruując i wykonując polecenia, należy zachować szczególną ostrożność. Jeśli jakakolwiek część polecenia do wykonania pochodzi z zewnętrznego źródła, należy dokładnie sprawdzić, czy wykonanie tego polecenia będzie bezpieczne. Sprawdzanie wszelkich danych przekazywanych do uruchomionego procesu powinna także przeprowadzać aplikacja AIR.

Sprawdzanie danych wejściowych może jednak nastręczać trudności. Aby uniknąć takich trudności, najlepiej stworzyć aplikację rodzimą (np. plik EXE w systemie Windows) udostępniającą określone wywołania interfejsu API. Te wywołania interfejsu API powinny przetwarzać wyłącznie konkretne polecenia zdefiniowane przez aplikację. Aplikacja może na przykład akceptować ograniczony zestaw instrukcji przesyłany za pośrednictwem standardowego strumienia wejściowego.

Środowisko AIR w systemie Windows nie pozwala na bezpośrednie uruchomienie plików .bat. Aplikacja interpretera poleceń (cmd.exe) uruchamia pliki .bat systemu Windows. Z chwilą wywołania pliku .bat aplikacja może zinterpretować argumenty przekazywane do polecenia jako dodatkowe aplikacje do uruchomienia. Jednak wstawienie dodatkowych znaków do ciągu argumentów może spowodować wywołanie przez interpreter cmd.exe szkodliwych lub niebezpiecznych aplikacji. Na przykład bez odpowiedniego sprawdzania danych aplikacja AIR może wywołać polecenie myBat.bat myArguments c:/evil.exe . Obok uruchomienia pliku wsadowego zostanie wówczas uruchomiona aplikacja evil.exe.