タイトルJava Watch on the X》3 - プロセス実行についての補足カテゴリーAppleScript, Java, Java Watch on the X
作成日2001/12/6 17:13:2作成者新居雅行
2001年11月28〜30日に渡り、Java Watch on the Xのコーナで『3 - 今度こそ「JavaからAppleScript」を実行する』として記事をお届けしたが、少し補足を行いたい。一連の記事はテーマとしては、JavaのアプリケーションからAppleScriptを実行するということではあるが、もっともポイントになるところは、java.lang.Runtimeクラスにあるexecメソッドによって、コマンドラインで与えて実行可能なプロセスを起動する方法である。
その後、いろいろなプログラムを触りながら気付いたことであるが、exec(String)と、exec(String[])のメソッドの動作にはやはり違いがある。特にファイル名の指定においては、後者のStringの配列を使う手法でないと機能しない場合があった。つまり、コマンドラインとしての文字列を1つのStringにするより、引数をそれぞれStringの配列で指定する方が、ファイル名でのトラブルには会いにくいようである。その場合は、パラメータも配列の1つの要素として指定することになる。指定するファイル名については、特にエンコードの変換はしなくても問題ないようだ。つまり、

Runtime.getRuntime().exec("open ’/Applications/ファイルメーカーPro 5.5/ファイルメーカーPro.app’");

は実際にはファイルメーカーProのアプリケーションは起動しない。標準出力を見ると、no such fileとエラーメッセージを見ており、ファイルパスの中にある空白を区切りと解釈してしまっているようである。一方、以下のようにStringの配列で指定すると、問題なく実行できる。

String com[] = {"open", "/Applications/ファイルメーカーPro 5.5/ファイルメーカーPro.app"};
Runtime.getRuntime().exec(com);

空白がないファイル名の場合でも、同様なことがあったが、その場合は日本語を含むファイル名であることが原因であると思われる。いずれにしても、パラメータの引き渡しをきちんと行うには、String配列を使った方のexecメソッドを使うのに限るようだ。

それから、サンプルプログラムのAppleScriptRunnerクラスにあるdoScriptメソッドでは、execでosascriptコマンドを実行していて、標準入出力などを扱っている。ここで、場合によっては、ProcessクラスにあるwaitForメソッドを使って、プロセスの終了を待つ方がいい場合もある。サンプルプログラムでは入れていないが、動作によっては入れた方がいいだろう。waitForで待ってから、osascriptからの標準出力を取り込むのが基本になると思われる。
どういう場合で問題になったかと言えば、AppleScriptRunnerを実行したCocoa-Javaアプリケーションで、指定したスクリプトを実行後、ダイアログボックスを表示するようにプログラムを組んだ。スクリプトでは、Finderをアクティブにしているのだが、そのスクリプトの実行が終わる前に、Cocoa-Javaアプリケーション側で処理が進んでダイアログボックスを表示し、Cocoa-Javaアプリケーションがアクティブになってしまったのである。ここでは、スクリプトの処理の間はFinderがアクティブになってほしいので、waitForメソッドでスクリプトの処理が終了するのを大人しく待つようにしたという次第である。

さらに、AppleScriptにまつわるポイントだ。Mac OSの時代から、AppleScriptのコマンドの一部は「そのアプリケーションをアクティブにしないと機能しない」という現象は稀に見られたが、やっぱりMac OS Xでもあるようだ。アクティブにする、つまりGUIのいちばん手前に持って行くのは、AppleScriptでは「activate」というコマンドだけでかまわない。
具体的には、Finderに対して、make new alias file ...として、エイリアスを作成するAppleScriptプログラムを、Cocoa-Javaの中で動かした。そのスクリプトだけを取り出して、Script Editorで実行するときちんと動いてエイリアスを作るのに、Cocoa-Javaアプリケーションの中ではなぜか動かない。しかもエラーも出ない。そこで、プログラムの最初に「activate」を入れたら、動きだしたと言うわけである。なぜか、Script Editor上では動くというのは若干解せないのではあるが、いずれにしても、Cocoa-JavaアプリケーションからFinderに切り替える作業をAppleScriptの中に忍び込ませることで、なんとか機能したという次第だ。
Mac OSの時代でも、たとえば、あるアプリケーションで作ったグラフをコピーして別のアプリケーションに持ち込むという場合には、背後のアプリケーションの状態でコピーしても、クリップボードには入れられなかった。Toolboxのクリップボードのメカニズムから、アプリケーション切り替え時に汎用的なクリップボード領域の内容が更新されるため、いずれにしても、コピーやペースとはアクティブなアプリケーションに対して行う以外は必ずしもうまくはいかないというのが原則であった。やはり、人間が使うように作られたアプリケーションは、背後で何かやれと言われてもそうはいかないのかもしれない。Mac OS Xでも同じようにアクティブにしないと機能しないスクリプトがあるというのは、理屈の上では釈然とはしないけれど、必要なノウハウのような気がする。
関連リンク