あるアプリケーションの名前は一定とは限らない

1997.01.18
1997.07.11
1998.04.26

追補:
 このアプリケーション名の不一致による問題ですが、AppleScript v1.1.2(MacOS8以降に標準添付)では解決されているようです。したがって以下の文章は、AppleScript v1.1以前の環境の方のみ参考にして下さい。


 AppleScriptでアプリケーションに命令を送るとき、スクリプト中ではアプリケーション名を指定しなければなりません。このため名前にバージョン番号や「FAT」、「J」等が付加されているアプリケーションの場合、そのアプリケーションをバージョンアップするたびにスクリプトを修正する必要があります。

 この問題の根本的な解決策は今のところありませんが、現状の考察と応急策を以下に記します。


 例えば「Netscape Navigatorェ 3.0」に対して命令する場合、普通次のように書きます。

tell application "Netscape Navigatorェ 3.0"
  activate
end tell
 このスクリプトを実行すれば、Netscape Navigatorがアクティブになります。この段階では、普通のアプリケーションのスクリプティングとなんら変わるところはありません。

 ところが、ユーザが新しいバージョンのNetscape Navigatorをインストールした場合、上のスクリプトを実行しようとすると「Netscape Navigatorェ 3.0を選択して下さい。」というダイアログが表示されます。スクリプト編集プログラムでスクリプトを開いている場合は、ここで新しいバージョンのものを選択すると次のようにスクリプトが書き換えられます。

tell application "Netscape Navigatorェ 3.01"
  activate
end tell
 これはこれで便利なのですが、このスクリプトがアプレットとして保存されていた場合、事態は少々深刻になります。

 「Netscape Navigatorェ 3.0」に対する命令を持つアプレットを「Netscape Navigatorェ 3.01」がインストールされた環境で実行すると、この場合もやはり「Netscape Navigatorェ 3.0を選択して下さい。」というダイアログが表示されます。ところがアプレットの場合、スクリプト内のアプリケーション名は変更されません。従って、ユーザがアプレットを実行するたびにアプリケーション選択のダイアログが現れることになります。

 これを回避するためには、ユーザが一度アプレットをスクリプト編集プログラムで開く必要があります。スクリプトを開くとき例のダイアログが現れるので、新しいバージョンのアプリケーションを選択すれば万事終了。めでたくアプリケーション名が更新されます。

 しかし… 例えばNetscape Navigatorに関するアプレットが20も30もある場合、ユーザは全てのアプレットをスクリプト編集プログラムで開き、アプリケーションを選択し直さなければなりません。またHyperCardにAppleScriptを埋め込んだり、FaceSpanでユーザインターフェイスを作成している場合、その手間はアプレットを更新することの比ではありません。そこで、バージョンが変わっても(つまりアプリケーションのファイル名が変わっても)問題なく動作するスクリプトを組む必要があるわけです。


1. アプリケーション名を変数で指定する


 まずアプレットの実行された環境に於けるNetscape Navigatorのアプリケーション名は、以下の方法で得ることができます。
tell application "Finder"
  name of application file id "MOSS"
end tell
 これで得られたアプリケーション名を変数「NSName」に代入すると、最初の例は
tell application NSName
  activate
end tell
 と記述できます。

 この例を実行してみると、ちゃんとNetscape Navigatorがアクティベートされるはずです。

 しかし喜ぶのはまだ早い。これを次のように記述するとどうなるでしょうか。

tell application NSName
  register protocol "FTCh" for protocol "ftp:"
end tell
 この例はコンパイルすらできないはずです。activateでは動作するのに、なぜ?

 これは、「activate」がアプレットにもNetscape Navigatorにも理解できる共通の命令であり、「register protocol」がNetscape Navigatorに特有の命令であることに起因します。

 AppleScriptでは構文確認の際に、tellで指定されたアプリケーションファイルの辞書情報を読み込みます。これによってそのアプリケーションに対するスクリプトの正誤が判定できるわけです。しかし、もし変数をtellの対象とした場合、AppleScriptはtellの対象となるアプリケーションがなにか理解できず、アプレットに対する命令とみなしてコンパイルします。

 アプレットは「open/activate/launch/quit」をサポートしていますので、これらの命令だけは問題なくコンパイルされるわけです。もちろん「register protocol」はNetscape Navigator特有の命令ですから、スクリプトには理解できません。したがって、実行はもちろん、コンパイルすら不可能となります。

 アプリケーション名を変数で代用する方法は、対象となるアプリケーションがアプレットである場合か、アプレットと全く同じ命令をサポートしているアプリケーションに対してのみ有効です。… 残念ながら。


2. テキストをスクリプトとみなして実行する


 AppleScriptでは、テキストをスクリプトとして直接実行することができます。例えば以下のように記述することによって、Finderがアクティブになります。
run script "tell application \"Finder\" to activate"
 その環境でのアプリケーション名は簡単に得られるわけだから、うまく名前とテキストを繋げて正しいスクリプトを作れば、アプリケーション名に依存しないスクリプトを組めるのではないか…

 結論から先にいうと、無理です。

 まず、正常に動作すると仮定しても、実行が極端に遅くなります。実際に上の例を実行してみれば分かりますが、本来なら一瞬で終了するはずの簡単なスクリプトですら、極端に「遅い」。はっきりいって使いものになりません。

 しかし、遅いだけなら我慢すればすみますが、実際にNetscape Navigatorを使ったスクリプトを組んでみると、ほとんど動作しないことが分かりました。

 例えば「activate」ですら、アプリケーションが起動していない状態ではうまく動作しません。なぜか「make new window」だけは正常に動作するのですが、それ以外はほとんど全滅。まったく動かないのです。

 仕様から考えれば、この方法では遅いにせよ正常に動作するはずです。しかし現実問題として、まともに動作しないのです。従って、このやり方も使えません。


3. アプリケーション名そのものを変更する


 もっともアグレッシブな方法です (^ ^;) Finderを利用して、アプリケーションのファイル名そのものを変更します。

 例えば以下のようにすれば、アプリケーション名は常に同じになります。

tell application "Finder"
  set name of application file id "MOSS" to "Netscape Navigatorェ"
end tell
 このスクリプトをアプレット形式で保存し、インストーラと称して使用すれば、その後いっさいアプリケーション名の問題からは解放されます。Netscape Navigatorに対するスクリプトは、次のように書くだけでいいでしょう。

tell application "Netscape Navigatorェ"
  register protocol "FTCh" for protocol "ftp:"
end tell
 もちろんちゃんと動作しますよ。当たり前ですが (^ ^;)

 この方法の問題点は、自分以外のユーザが使用するとき、アプリケーションのファイル名を変更する旨をあらかじめ説明しておかなければならないことです。Macユーザは基本的にRead Meなど全く読まずにアプリケーションを試すのが常ですから、これは結構重大な問題です。もちろんそれ以前に、既存のアプリケーションのファイル名を変更するということが著作権に触れそうですが。

 しかしここで挙げている例の中では唯一問題を解決している方法が、これです (^ ^;) しかたなく筆者(Karino)は個人的なスクリプトに関してのみこの方法を採用しています。

 普通は使えませんよね。こんなやり方は。


4. AppleEventを直接書く


 多少なりと専門的な知識がいりますが、アプリケーションファイルの名称に関係なく命令を記述する方法もあります。それは、AppleEventを直接書き込んでしまうという方法です。

 例えば次のようにスクリプトを記述すると、Netscape Navigatorのバージョンに関係なくスクリプトを実行できるようになります。

tell application "Finder"
  set NSName to name of application file id "MOSS"
end tell
tell application NSName
  ヌevent WWW!RGPRネ "FTCh" given ヌclass PROTネ:"ftp:"
end tell

 ただしこの方法は、ResEditなどのリソースエディタを使ってaeteリソースを覗き、自力で命令を組み立てなければなりません。それにスクリプトの変更を行う場合、かなりの労力が必要になってしまいます。従ってこの方法は、ある程度AppleScriptの裏舞台を知ってから行った方がいいと思います。


 というわけで、この問題に対する根本的な解決策はありません。これはAppleScriptの仕様ですから、本来アプリケーションの側で対応すべき問題のはずです。アプリケーションの制作者は、アプリケーション名にバージョン番号や動作環境(例えばPPCやFAT、68Kなどといった文字列)、ローカライズに関する情報(例えばJ)を加えるべきではありません。それらはフォルダやversリソースで表現すればすむことだからです。

 しかし、現実にはそのような情報を付加したアプリケーション名がまかり通っています。自分でアプリケーションを制作している人は気をつけて下さい。同じアプリケーションのファイル名は、常に同じであるべきなのです。

 以上、現状の考察と応急策でした。


註)FaceSpanは、v2.0以降アプリケーションファイル名が変化しても問題がおきないように工夫されているそうです。

Tipsに戻る
AppleScriptのページに戻る
このホームページに関するお問い合わせは、karino@drycarbon.comまで。