與 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 屬性的 write 方法,將資料寫入標準輸入串流。當 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(); 
}

從標準輸出串流讀取

使用這個屬性的 read 方法,就可以從標準輸出串流讀取資料。 當 AIR 應用程式從程序取得輸出串流資料後,NativeProcess 物件會傳送 standardOutputData 事件。

若寫入標準輸出串流時發生錯誤,NativeProcess 物件會傳送一個 standardOutputError 事件。

程序關閉輸出串流之後,NativeProcess 物件會傳送一個 standardOutputClose 事件。

讀取標準輸入串流中的資料時,請確認在資料產生時就進行讀取。換言之,即新增 standardOutputData 事件的事件偵聽程式。在 standardOutputData 事件偵聽程式中,讀取 NativeProcess 物件之 standardOutput 屬性的資料。而不要只是等待 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); 
}

從標準錯誤串流讀取

使用這個屬性的 read 方法,就可以從標準錯誤串流讀取資料。 當 AIR 應用程式從程序讀取錯誤串流資料後,NativeProcess 物件會傳送 standardErrorData 事件。

若寫入標準錯誤串流時發生錯誤,NativeProcess 物件會傳送一個 standardErrorIoError 事件。

程序關閉錯誤串流後,NativeProcess 物件會傳送 standardErrorClose 事件。

讀取標準錯誤串流中的資料時,請確認在資料產生時就進行讀取。換言之,即新增 standardErrorData 事件的事件偵聽程式。在 standardErrorData 事件偵聽程式中,讀取 NativeProcess 物件之 standardError 屬性的資料。而不要只是等待 standardErrorClose 事件或 exit 事件,才讀取所有資料。如果您未在原生程序產生資料時讀取資料,則緩衝區可能會填滿,資料可能會因而遺失。緩衝區填滿後,如果嘗試寫入更多資料,會導致原生程序變得遲緩。不過,如果您未註冊 standardErrorData 事件的事件偵聽程式,則緩衝區不會填滿,程序也不會變得遲緩。在此情況下,您無法存取資料。

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 應用程式。