Apple Developer Connection
Advanced Search
Member Login Log In | Not a Member? Contact ADC


コマンドラインユーティリティへのアクセス

Dashboardには、ウィジェットの中でコマンドラインユーティリティやスクリプトを使う手段が用意されています。この手段を利用することで、システムに付属する任意の標準ユーティリティや、ウィジェットに含める任意のユーティリティまたはスクリプトを使用できます。

注: 本章を読み進める前に、“アクセスキーの指定”を読み、ウィジェットのアクセスキーの詳細を学習しておきましょう。

In this section:

システムメソッド
同期動作
非同期動作


システムメソッド

コマンドラインユーティリティまたはスクリプトをウィジェット内で実行するには、widget.system()メソッドを使う必要があります。メソッドは次のように定義されています。

widget.system("command", handler)

widget.system()メソッドのパラメータは次のとおりです。

Table 14  widget.system() パラメータ

パラメータ

定義

command

コマンドラインユーティリティを指定する文字列。パラメータとフラグを含むことができます。

"/bin/ls -l -a"

handler

コマンドラインユーティリティの実行が完了したときに呼び出す関数。また、コマンドを同期モード、非同期モードのどちらで実行するかを切り替えます。このハンドラを指定した場合、ハンドラは引数を受け取る必要があります。

systemHandler

注: コマンドを指定するときは、コマンドへの完全パス、または、ウィジェットのルートレベルからの相対パスを必ず指定してください。パスが不確かな場合は、whichコマンドを使って調べることができます。

また、widget.system()にコマンドを渡すときに、標準以外の環境変数、カスタムの検索パス、「ターミナル」環境設定に依存しないようにしてください。

handlerパラメータとして何を渡したかに応じて、widget.system()への呼び出しは、同期または非同期のどちらかのモードで動作します。

同期動作

widget.system()を同期的に使う」とは、実行するコマンドの結果が得られるまでウィジェットの実行を保留することを意味します。同期動作は、出力を一度だけ行い、実行が短時間で終わるコマンドを使う場合に利用します。

注: widget.system()の同期的な使用は、開発とデバッグの目的で使う場合に限りお勧めします。widget.system()を同期的に使うウィジェットは、配布しないでください。出荷用のウィジェットを配布するときには、“非同期動作”で説明するように、widget.system()を非同期的に使用してください。

同期動作の例として、ウィジェットの中からidコマンドを実行することが考えられます。

widget.system("/usr/bin/id -un", null);

最初の引数は、実行するコマンドを示します。ここでは、idに -unフラグを指定して実行しています。コマンドに対してイベントハンドラを指定していないので、コマンドが完了するまでウィジェット内の動作はすべて停止します。

上のように指定するとidコマンドは実行されますが、情報が必要であることを指定していないので出力はすべて失われます。コマンドの出力を得るには、outputStringプロパティを指定して出力を変数に保存します。

var output = widget.system("/usr/bin/id -un", null).outputString;

widget.system()を同期的に使う場合には、出力文字列、エラー文字列、またはコマンドの出力ステータスを取得できます。

Table 15  同期動作でのwidget.system()

プロパティ

定義

使用法

outputString

stdout(標準エラー出力)に出力されるコマンドの出力。

var output = widget.system("id -un", null).outputString;

errorString

stderr(標準エラー出力)に出力されるコマンドの出力。

var error = widget.system("id -un", null).errorString;

status

コマンドの終了ステータス。

var status = widget.system("id -un", null).status;

サンプルコード

The Which Widget

Xcode Toolsをインストールしたあと、ハードディスクの/Developer/Examples/Dashboard/にあるウィジェットのサンプルコードに、「Which」ウィジェットが含まれています。このウィジェットは、whichコマンドラインユーティリティをウィジェットでラップしてフロントエンドとする簡単な例です。

ウィジェットのアクションボタンがメソッドを呼び出します。このメソッドは、widget.system()を使用して、指定された文字列を対象にwhichを呼び出し、返された出力文字列をウィジェットに返します。

document.getElementById("outputText").value = widget.system("/usr/bin/which "+ document.getElementById("inputText").value, null).outputString;

すでに述べたように、ウィジェット内のコードの実行は、widget.system()の結果を待機します。whichのような単純なコマンドであれば、この方法には何も問題はありません。しかし、実行の時間が長いコマンドや、実行中に入力が必要なコマンドもあります。そのようなコマンドの場合には、widget.system()の非同期動作モードを利用します。

非同期動作

widget.system()の第2引数としてハンドラを渡すと、コマンドは非同期モードで実行します。これは、ウィジェット内の実行が、コマンドの実行中も継続することを意味します。指定したハンドラは、コマンドが完了すると呼び出され、パラメータとしてオブジェクトを1つ受け取る必要があります。オブジェクトには、コマンドが実行を完了したときの最後の出力が含まれています。このオブジェクトから、次のプロパティを取得することができます。

Table 16  widget.system() 終了ハンドラパラメータオブジェクトのプロパティ

プロパティ

定義

object.outputString

stdout(標準エラー出力)に出力されるコマンドの最後の出力。

object.errorString

stderr(標準エラー出力)に出力されるコマンドの最後の出力。

object.status

コマンドの終了ステータス。

コマンドは非同期で実行しているので、実行中にコマンドとやり取りする必要が生じることもあります。widget.system()を非同期で使用すると、コマンドとの以後のやり取りに使用できるオブジェクトが返されます。

var myCommand = widget.system("/sbin/ping foo.bar", endHandler);

返される(そして、myCommandに保存される)オブジェクトは、いくつかのメソッドに応答し、さまざまなプロパティを持っています。

Table 17  非同期動作で利用できるwidget.system()のプロパティとメソッド

選択肢

目的

説明

myCommand.outputString

プロパティ

コマンドによってstdout(標準出力)に書き出された現在の文字列。

myCommand.errorString

プロパティ

コマンドによってstderr(標準エラー出力)に書き出された現在の文字列。

myCommand.status

プロパティ

コマンドによって定義される、コマンドの終了ステータス。

myCommand.onreadoutput

イベントハンドラ

コマンドがstdoutに書き出しを行うたびに呼び出される関数。ハンドラは1つ受け取る必要があります。呼び出し時には、stdoutに出力された現在の文字列が引数として渡されます。

myCommand.onreaderror

イベントハンドラ

コマンドがstderrに書き出しを行うたびに呼び出される関数。ハンドラは1つ受け取る必要があります。呼び出し時には、stderrに出力された現在の文字列が引数として渡されます。

myCommand.cancel()

メソッド

コマンドの実行を取り消します。

myCommand.write(string)

メソッド

stdin(標準入力)に文字列を書き出します。

myCommand.close()

メソッド

stdinを閉じます(EOF)。

たとえば、pingコマンドを実行し、コマンドがstdoutに何かを書き出すたびに通知を受けるには、次のコードを使用します。

var myCommand = widget.system("/sbin/ping foo.bar", endHandler);
myCommand.onreadoutput = outputHandler;

あるいは、次のコードを使用できます。

widget.system("/sbin/ping foo.bar", endHandler).onreadoutput = outputHandler;

指定したonreadoutputハンドラは、引数を受け取る必要があります。ハンドラの呼び出し時には、stdoutに書き出された最新の文字列が渡されます。

function outputHandler(currentStringOnStdout){    // コマンドの現在の出力を使って何かを行うコマンド。たとえば・・・
    document.getElementById("element").innerText = currentStringOnStdout;}

pingのようなコマンドはいつまでも実行を続けるので、ある時点で実行を終了する必要があります。それには、widget.system()から受け取ったオブジェクトを対象に、cancel()メソッドを使用します。

myCommand.cancel();

コマンドの中には、bcのように、実行のある時点で入力を必要とするものもあります。コマンドが入力を想定している標準入力に書き出しを行うには、write()メソッドを使用します。

myCommand.write("8*5");

これらのコマンドを(ファイル終了シグナル、すなわち EOFシグナルを使用して)正しく閉じるには、close()を使用します。

myCommand.close();

このコマンドが非同期で動作するように、実行の終了に対するイベントハンドラを指定する必要があることを忘れないでください。ハンドラには、widget.system()を最初に実行したときに作成されたオブジェクトが渡されます。これは、コマンドのステータスコードを取得できることを意味します。また、onreadoutputハンドラまたはonreaderrorハンドラを使用しなかった場合に、stdoutまたはstderrへのコマンドの出力の全体をそれぞれ取得することが可能です。

サンプルコード

The Voices Widget

Xcode Toolsをインストールしたあとハードディスクの/Developer/Examples/Dashboard/に置かれるVoicesサンプルコードでは、widget.system()を非同期的に使用しています。Voicesを開くと、最初に自己紹介が聞こえます。

function setup()
{
    if (window.widget) {
        currentlyBeingSpoken = widget.system("/usr/bin/osascript -e 'say \"Welcome to Voices!\" using \"Fred\"'" , doneSpeaking);
    }
}

コマンドの実行終了に対するハンドラを指定すれば、コマンドは非同期で動作します。グローバル変数currentlyBeingSpokenにコマンドオブジェクトを代入することで、必要に応じて実行中にオブジェクトに対してコマンドを発行できるようにしています。コマンドの完了時に呼び出されるdoneSpeaking()関数は、currentlyBeingSpokenNULLに設定します。

あとで、ユーザがしゃべらせる言葉を入力すると、次のコードが呼び出されます。

if (window.widget) {
    if(currentlyBeingSpoken != null) {
        currentlyBeingSpoken.cancel();
    }
    currentlyBeingSpoken = widget.system("/usr/bin/osascript -e 'say \"" + textToSpeak + "\" using \"" + chosenVoice + "\"'" , done);
}

ここでは、currentlyBeingSpokenを調べてコマンドが実行中でないか調べています。実行中の場合、コマンドに対してcancel()を呼び出して停止し、新しいコマンドを発行します。done()関数は、ユーザインターフェイスの調整をいくらか行ってから、doneSpeaking()を呼び出してcurrentlyBeingSpokenNULLに設定します。

Voicesは、メニューの中で声が選択されるたびにその声で自己紹介をします。そのためのコードは、前のサンプルと同様のロジックを踏襲します。

function voiceChanged(elem)
{
    var chosenVoice = elem.options[elem.selectedIndex].value;
    document.getElementById("voiceMenuText").innerText = chosenVoice;
 
    if (window.widget) {
        if(currentlyBeingSpoken != null) {
            currentlyBeingSpoken.cancel();
            done();
        }
        currentlyBeingSpoken = widget.system(
                    "/usr/bin/osascript -e 'say \"Hi, I`m " +
                    chosenVoice + ".\" using \"" +
                    chosenVoice + "\"'" ,
                    doneSpeaking
                    );
    }
}




Last updated: 2006-08-07




Did this document help you?
Yes: Tell us what works for you.

It’s good, but: Report typos, inaccuracies, and so forth.

It wasn’t helpful: Tell us what would have helped.
Get information on Apple products.
Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Copyright © 2007 Apple Inc.
All rights reserved. | Terms of use | Privacy Notice