AIR のネイティブプロセスとの通信

Adobe AIR 2 以降

Adobe AIR 2 では、AIR アプリケーションの実行や他のネイティブプロセスとの通信を、コマンドライン経由で行うことができます。例えば、AIR アプリケーションでは、プロセスを実行し、標準の入出力ストリームを使用してそのプロセスと通信できます。

ネイティブプロセスと通信するには、ネイティブインストーラーでインストールされるように AIR アプリケーションをパッケージ化します。ネイティブインストーラーのファイルタイプは、そのインストーラーが作成されたオペレーティングシステムに固有のものです。

  • Mac OS では DMG ファイルです。

  • Windows では EXE ファイルです。

  • Linux では RPM または DEB パッケージです。

これらのアプリケーションは、拡張デスクトッププロファイルアプリケーションとして知られています。ネイティブインストーラーを作成するには、ADT を使用して -package コマンドを呼び出すときに、 -target native オプションを指定します。

ネイティブプロセス通信の概要

拡張デスクトッププロファイルの AIR アプリケーションでは、コマンドラインでファイルを呼び出すときと同様にファイルを実行できます。また、ネイティブプロセスの標準ストリームと通信することができます。標準ストリームには、標準入力ストリーム(stdin)、出力ストリーム(stdout)、標準エラーストリーム(stderr)が含まれます。

注意: 拡張デスクトッププロファイルのアプリケーションでは、 File.openWithDefaultApplication() メソッドを使用してファイルおよびアプリケーションを起動することもできます。ただし、このメソッドを使用しても、AIR アプリケーションは標準ストリームにアクセスできません。詳しくは、 デフォルトのシステムアプリケーションでファイルを開く を参照してください。

次のコードサンプルは、アプリケーションディレクトリで test.exe アプリケーションを起動する方法を示しています。アプリケーションは、引数 "hello" をコマンドライン引数として渡し、プロセスの標準出力ストリームにイベントリスナーを追加します。

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

ネイティブプロセスの起動および終了

ネイティブプロセスを起動するには、次の処理を行うように NativeProcessInfo オブジェクトを設定します。

  • 起動するファイルを参照する

  • 起動時にプロセスに渡すコマンドライン引数を保存する(オプション)

  • プロセスの作業ディレクトリを設定する(オプション)

ネイティブプロセスを起動するには、NativeProcessInfo オブジェクトを、NativeProcess オブジェクトの start() メソッドのパラメーターとして渡します。

例えば、次のコードは、アプリケーションディレクトリで test.exe アプリケーションを起動する方法を示しています。アプリケーションは引数 "hello" を渡し、ユーザーのドキュメントディレクトリを作業ディレクトリとして設定します。

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

プロセスを終了するには、NativeProcess オブジェクトの exit() メソッドを呼び出します。

インストールされたアプリケーションでファイルを実行可能にする場合には、アプリケーションをパッケージ化するときに、対象のファイルシステムでそのファイルが実行可能であることを確認してください(Mac と Linux では、必要に応じて、chmod を使用して実行可能フラグを設定できます)。

ネイティブプロセスとの通信

AIR アプリケーションでは、ネイティブプロセスを起動したら、プロセスの標準入力ストリーム、標準出力ストリーム、および標準エラーストリームと通信できます。

ストリームのデータの読み取りおよび書き込みは、NativeProcess オブジェクトの次のプロパティを使用して行います。

  • standardInput — 標準入力ストリームデータへのアクセスを含みます。

  • standardOutput — 標準出力ストリームデータへのアクセスを含みます。

  • standardError — 標準エラーストリームデータへのアクセスを含みます。

標準入力ストリームへの書き込み

標準入力ストリームにデータを書き込むには、NativeProcess オブジェクトの standardInput プロパティの書き込みメソッドを使用します。AIR アプリケーションがプロセスにデータを書き込むと、NativeProcess オブジェクトは standardInputProgress イベントを送出します。

標準入力ストリームへの書き込みでエラーが発生すると、NativeProcess オブジェクトは ioErrorStandardInput イベントを送出します。

入力ストリームを終了するには、NativeProcess オブジェクトの closeInput() メソッドを呼び出します。入力ストリームが終了するとき、NativeProcess オブジェクトは 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(); 
}

標準出力ストリームからの読み取り

標準出力ストリームからデータを読み取るには、このプロパティの読み取りメソッドを使用します。AIR アプリケーションがプロセスから出力ストリームデータを受信すると、NativeProcess オブジェクトは standardOutputData イベントを送出します。

標準出力ストリームへの書き込みでエラーが発生すると、NativeProcess オブジェクトは standardOutputError イベントを送出します。

出力ストリームが終了するとき、NativeProcess オブジェクトは standardOutputClose イベントを送出します。

標準データストリームからデータを読み取るときは、生成時にデータを読み取ってください。言い換えると、 standardOutputData イベントのイベントリスナーを追加します。 standardOutputData イベントリスナーで、NativeProcess オブジェクトの standard utput プロパティからデータを読み取ります。 standardOutputClose イベントまたは exit イベントがすべてのデータを読み取るのを待たないでください。ネイティブプロセスが生成するときにデータを読み取らないと、バッファーがいっぱいになるか、データが失われる可能性があります。バッファーがいっぱいになると、さらにデータを書き込もうとしたときにネイティブプロセスがストールすることがあります。ただし、 standardOutputData イベントのイベントリスナーを登録しない場合、バッファーはいっぱいにならず、プロセスはストールしません。この場合、データにアクセスすることはできません。

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

標準エラーストリームからの読み取り

標準エラーストリームからデータを読み取るには、このプロパティの読み取りメソッドを使用します。AIR アプリケーションがプロセスからエラーストリームデータを読み取ると、NativeProcess オブジェクトは standardErrorData イベントを送出します。

標準エラーストリームへの書き込みでエラーが発生すると、NativeProcess オブジェクトは standardErrorIoError イベントを送出します。

エラーストリームが終了するとき、NativeProcess オブジェクトは standardErrorClose イベントを送出します。

標準エラーストリームからデータを読み取るときは、生成時にデータを読み取ります。言い換えると、 standardErrorData イベントのイベントリスナーを追加します。 standardErrorData イベントリスナーで、NativeProcess オブジェクトの standardError プロパティからデータを読み取ります。 standardErrorClose イベントまたは exit イベントがすべてのデータを読み取るのを待たないでください。ネイティブプロセスが生成するときにデータを読み取らないと、バッファーがいっぱいになるか、データが失われる可能性があります。バッファーがいっぱいになると、さらにデータを書き込もうとしたときにネイティブプロセスがストールすることがあります。ただし、 standardOutputData イベントのイベントリスナーを登録しない場合、バッファーはいっぱいにならず、プロセスはストールしません。この場合、データにアクセスすることはできません。

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

ネイティブプロセス通信のセキュリティ上の考慮事項

ネイティブプロセス API は、ユーザーのシステム上で任意の実行可能ファイルを実行できます。コマンドの構築時および実行時には、十分に注意を払ってください。実行されるコマンドが一部でも外部ソースから発行されている場合には、そのコマンドを実行しても安全であるかどうかを慎重に検証してください。同様に、AIR アプリケーションにおいても、実行中のプロセスに渡されるデータを検証する必要があります。

ただし、入力を検証することは難しい場合があります。このような問題を回避するには、特定の API を含むネイティブアプリケーション(Windows 上の EXE ファイルなど)を作成することが最適です。これらの API は、アプリケーションによって定義されるコマンドのみを処理する必要があります。例えば、アプリケーションは標準入力ストリームを介して限られたセットのインストラクションのみを受け付けることができます。

Windows 上の AIR は、ユーザーが .bat ファイルを直接実行することを許可しません。コマンドインタープリターアプリケーション(cmd.exe)は、Windows の .bat ファイルを実行します。.bat ファイルを呼び出すとき、このコマンドアプリケーションは、コマンドに渡される引数を、起動する追加のアプリケーションとして解釈することができます。引数のストリングに悪質な意図で不要な文字が挿入されている場合、有害または安全ではないアプリケーションを cmd.exe が実行するおそれがあります。例えば、妥当なデータ検証が行われない場合、AIR アプリケーションが myBat.bat myArguments c:/evil.exe を呼び出す可能性があります。このコマンドアプリケーションは、バッチファイルを実行するときに、一緒に evil.exe アプリケーションを起動することになります。