AppleScript

出典: フリー百科事典『ウィキペディア(Wikipedia)』
移動先: 案内検索
AppleScript
パラダイム オブジェクト指向スクリプト言語
登場時期 1993年
型付け 弱い動的型付け
影響を受けた言語 HyperTalkObjective-C
プラットフォーム System7Mac OS 8Mac OS 9Mac OS X
ウェブサイト AppleScript Overview
拡張子 .applescript .scpt .scptd

AppleScript(アップルスクリプト)は、アップルが開発したMac OS用のオブジェクト指向スクリプト言語。System 7(Mac OS 7にあたる)から採用されている。

標準環境で利用でき、ある程度自然言語英語)に似た構文を持つ。制御構文ハンドラ変数オブジェクトプロパティの記述といったプログラミングの基本機能を言語に備えており、Mac OSのプロセス間通信機能の一つであるApple eventによって、システムや様々な対応アプリケーションにまたがって制御できる。

AppleScriptはMac OSのスクリプティング機構Open Scripting Architecture(OSA)に対応した言語(OSA言語)のひとつであり、Mac OS X v10.10よりJavaScript for Automation(JXA)も標準搭載されるようになった[1]

特徴[編集]

カバーエリアの広さ[編集]

アプリケーション操作の自動化、shell commandの呼び出し、画面上の部品の強制操作にWebコンテンツの強制コントロール、Cocoa Frameworkの呼び出しにiCloud経由のコンテンツ更新など、マクロ言語としてはカバーできる範囲がとても広い。そのうえ、GUIベースのアプリケーション開発まで行えるため、いったん覚えるとMacを用いた作業の生産性が向上する。ただし、あまりに無節操に強化されリーチできる機能が多すぎるため、セキュリティーを考慮しさまざまな抑止機能がOSに用意されつつある。

Mac OS、Mac OS Xを通じて継承された唯一のテクノロジーであり[2]、海外を中心に強力な開発者コミュニティを形成している[3]。コミュニティ内で、GUIベースのアプリケーションのコントロールについて蓄積された膨大な知見は他に類を見ない。

仕組み[編集]

AppleScriptはOSAに準拠したスクリプト言語の一つであり、アプリケーション等のプロセスApple eventを送ることにより自動操作を実現する。そういった意味ではマクロ言語と同等。しかし実際にはプログラミング言語の一種であり、通常はコンパイル済みのバイトコードが保存され実行される。このため、基本的にはOSのバージョンやCPUの形式(68k、PPC、Intel(x32)、Intel(x64))、記述した言語(AppleScript英語、AppleScriptフランス語、AppleScript日本語)などに依存しないコードが生成される。

AppleScriptの言語そのものが定義している予約語(複数の単語による連語から構成される)は数十程度と少なく[4]、標準では絶対値を求める機能や三角関数の機能すら持たないが、Scripting Additions/OSAX(Open Scripting Architecture eXtension)[5]と呼ばれる機能拡張書類、あるいはAppleScriptそのもので記述したAppleScript Librariesによって命令を増やすことが可能となっている。

AppleScriptはMac OS上のアプリケーション間通信を基礎技術として用いているため、アプリケーションがApple eventに対応していればそのアプリケーションに処理を委ね、その処理結果を別のアプリケーションに対して用いることも可能である。また、現在のバージョンではGUI Scriptingと呼ばれる(AppleはUI Element Scriptingと呼んでいる)機能を用いて、スクリプトからアプリケーションにメニュー操作やキー入力を伝達することさえも可能になっている。アプリケーションは、システム経由で送られてきたApple eventメッセージを解釈して対応した処理を行い、処理結果を再びシステムを経由してApple eventメッセージとして返す。

インタプリタ型の逐次実行言語であるため、必然的にコンパイル型の言語に比べると実行速度は劣るが、アプリケーションの機能呼び出しを行わない場合には高速。ただし、アプリケーションの機能呼び出しはコストも高く、前述のGUI Scriptingを用いたメニューなどの強制操作を行うと、さらに処理コストが増加し、時間がかかる。

ユーザインタフェース[編集]

AppleScriptは、簡素なダイアログ(display dialog)、ノーティフィケーションセンターへのノーティファイ(display notification)、ポップアップメニューからの項目選択ダイアログ(choose from list)、ファイル選択(choose file)、フォルダ選択(choose folder)、新規ファイル保存先パス選択(choose file name)などの、目的に特化した簡単なユーザインタフェースを提供している。

これら以外のユーザインタフェースを利用するために、現在利用できる手段で一番簡単なやり方は、FileMakerで画面を作成し、ボタンに対してスクリプトステップ「AppleScriptを実行」を割り当てておくというものである。

Adobe InDesignなどの一部のアプリケーションでは、簡易的なユーザーインタフェースをAppleScriptのプログラムから動的に生成する機能を備えている。

本格的な、自由度の高い自作のインタフェースを持たせるには、Xcode上で「Cocoa-AppleScript Applet」プロジェクトを作成し、その中にAppleScriptコード(AppleScriptObjC)を記述する。Xcode上で一般のアプリケーション開発と同様にユーザインタフェースを作成できる。コントロール(GUIの部品)が操作されると、AppleScriptコード中の対応するイベントハンドラが呼び出される。

開発環境[編集]

Mac OS Xにはスクリプトの編集・実行ツールであるスクリプトエディタ(Mac OS X v10.0〜v10.4はスクリプトエディタ、Mac OS X v10.5〜v10.9はAppleScriptエディタMac OSでは『スクリプト編集プログラム』)が付属する。

スクリプトエディタにAppleScript対応アプリケーションのアイコンをドラッグ&ドロップするとAppleScript用語辞書が表示され、これを参照しつつアプリケーションのコントロールを行う処理を記述する。

スクリプトエディタにはブレークポイント設定や変数内容のモニタリングなどの機能はないため、これらの機能を利用したいユーザーはLate Night Software社の「Script Debugger」を用いる必要がある。また、Cocoaオブジェクトのログ表示やAppleScript Librariesに添付するAppleScript用語辞書の編集については、Shane Stanleyのシェアウェア「ASObjC Explorer 4」[6]を利用する必要がある。

その一方で、AppleScriptへのコードサインはApple純正のスクリプトエディタ上でしか行うことができない。

その他、テキストで書いたスクリプトをコマンドラインからosascriptコマンドでコンパイル・実行することも可能。

アップル純正の統合開発環境Xcode(旧Project Builder)上でAppleScriptによるアプリケーション開発を行うこともできる。AppleScriptから直接Cocoaの機能を呼び出せる「AppleScriptObjC」[7]が提供されている(Mac OS X v10.1〜v10.5ではAppleScript Studio)。ユーザーインタフェース作成についてInterface Builderを用いる点は以前のAppleScript Studio(Mac OS X v10.6で廃止)とかわりないが、AppleScript用語辞書を用いて各種GUI部品にアクセスするのではなく、Interface Builder上でバインディングによりAppleScriptプログラム中のプロパティ値にひもづけしたり、Cocoaの各種フレームワーク内のメソッドを呼び出す方式に変更された。

異なるOSバージョン間の互換性[編集]

AppleScript書類のフォーマットは維持されているため、基本的には互換性が確保されている。これまで、Mac OS X v10.4のIntel移行、Mac OS X v10.7の64bit移行などのOSの基盤の大変革期があったが、AppleScriptそのものについてはほぼ影響はなかった。AppleScriptの処理系そのものの変更が小刻みであったため、15年前に作られたソートルーチンがそのまま使えたりもする。

ただし、AppleScriptだけでなくOSAXや外部のアプリケーションの機能を利用していた場合には、部品ごとに確認が必要となる。

まず、Mac OS X標準添付のアプリケーションの機能がOSバージョンごとに異なる。これらを呼び出す処理を行っている場合にはチェックが必要。とくに、AppleScriptにOSの機能を提供するために用意されている補助アプリケーションはOSバージョンによって変更されることがあるため、その存在および代替機能を確認する必要がある。一般的に、古いバージョンから新バージョンへの移行は、それなりに手間はかかるものの確認作業レベルで済む。

逆に、新しいバージョンのOSから古いバージョンのOSにScriptを移植する場合には大幅に作業量が増える。古いOSには固有のバグもあるため(Mac OS X v10.5以前は日本語のパスの扱いに問題があった)、それらを考慮した処理に変更する必要も生じる。古いMac OS Xが動作する実機と関連アプリケーションを用意し、きちんと動作検証や書き換え作業が必要になる。

GUI Scriptingを利用している場合には、メニュー構成やボタンの文字を変えただけで動かなくなる可能性があるため、そもそも異なるOSバージョン間でそのまま動く可能性は低い(修正内容は単純)。

Mac OS X v10.10以降ではAppleScript側が想定するAppleScript処理系のバージョン(=Mac OS Xそのもののバージョン)をuseコマンドを使って表記できるようになった。「use AppleScript version "2.4"」だとMac OS X v10.10を、「use AppleScript version "2.5"」だとMac OS X v10.11を意味する。

構文[編集]

HyperCard用のスクリプト言語であるHyperTalkに似た、英語に近い構文が採用されており、基本的には習得しやすい。機能の異なるアプリケーションを操作するためには、それぞれアプリケーションごとに異なる命令やオブジェクト構造を知る必要があり、AppleScript対応アプリケーションのアイコンをスクリプトエディタでオープンすることで表示される「AppleScript用語辞書」を参照しつつ記述することになる。

初期は日本語表現形式を含む英語以外の言語による記述も可能だったが、Mac OS 8.5以降は英語表現形式のみが採用されている。英語表現形式の場合も変数名は | で囲むことで日本語などを使用できる。

Mac OS X v10.10でAppleScriptObjCがXcode上のみならず、スクリプトエディタ上でも利用できるようになったため、Objective-C風の表記も標準採用された。

スクリプトの例(変数「持ち物=myItem」の中身が0だったらダイアログを表示する)

英語

if myItem = 0 then
    display dialog "持ち物がありません" buttons {"OK"} default button "OK"
end if

通常は上記のように記述するが、より英文に近い以下のようなコードも記述できる。ただし複数の処理を一行のif文に組み込むことはできないので、先ほどの構文を使用することになる。下記のコードでは比較演算子の“等価”を表す = が is に置き換えられている。

if myItem is 0 then display dialog "持ち物がありません" buttons {"OK"} default button "OK"

変数名に日本語を用いた例

if |持ち物| is 0 then display dialog "持ち物がありません" buttons {"OK"} default button "OK"

日本語(現在は利用できない)

もし「持ち物」が0ならば
    “持ち物がありません”をボタンリスト:{“OK”}、デフォルトボタン:“OK”で表示する
以上

AppleScriptObjC構文[編集]

Mac OS X v10.6で部分的に導入され(Xcode上のみ)、Mac OS X v10.10でスクリプトエディタでもCocoaの機能を利用するAppleScriptObjCが導入された。このため、現行のMac OS X上ではどのマシンでもAppleScriptからCocoaの機能を利用できる状態になっている。

AppleScriptObjCは従来のAppleScriptと比べて10倍以上の高速処理が可能[8][9]。ただし、それはCocoaのメソッドを呼び出した場合であり、従来型のAppleScriptをAppleScriptObjC環境で記述しても速度は変わらない。

また、AppleScriptObjCではObjective-CのBlocks構文やprotocolをサポートしていないため、Cocoaのフレームワークすべてが利用できるわけではない。Cocoaのクラス名やメソッド名でAppleScriptの予約語とコンフリクトするものについては「|」で囲う必要がある(例:NSURL、URL、document、count、properties など)。ドットシンタックスもサポートしていないため、現行のObjective-C 2.0にくらべるとやや冗長な表記になる。

Objective-Cの表記をAppleScriptObjCに書き換えるには多少の慣れが必要。また、Cocoaオブジェクトの結果表示やログ表示については、Mac OS X標準添付のスクリプトエディタではサポートしていない。Cocoaオブジェクトのログ表示などを利用するためにはサードパーティの開発ツール「ASObjC Explorer 4」の利用が必要。


スクリプトの例(変数「aString」のアルファベット大文字を小文字に変換する)

Objective-C

NSString *aString = @"123/abc/ABC.txt";
[aString lowercaseString];

AppleScriptObjC

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aString to current application's NSString's stringWithString:"123/abc/ABC.txt"
(aString's lowercaseString()) as string

AppleScript対応アプリケーションへのtellブロック内でAppleScriptObjCの命令を呼び出すとエラーになる。このため、たとえばAdobe InDesignの書類から得られたデータをAppleScriptObjCを用いて高速にソートしたい場合などは、AppleScriptObjCの機能部分をサブルーチンとして分離し、InDesignへの命令ブロックと明示的に分ける必要がある。

なお、AppleScriptObjCで実行されるCocoa機能呼び出しはARC環境下で実行されるため、releaseなどのメソッドを呼び出すと実行環境ごとクラッシュする。

アプリケーション操作対象[編集]

アプリケーションを操作し、作業の自動化や、複数のアプリケーションを操作することでソフトウェア・ロボットを構築することが可能だが、操作対象の種類によって利用する技術や手法が変わる。

ローカルアプリケーション[編集]

Safariやコンタクト、カレンダーなどのMac OS X標準添付アプリケーションの多くがAppleScriptからのコントロールに対応しており、主要機能にアクセスできる。

ただし、対応アプリケーションであっても機能のすべてがAppleScriptに解放されているわけではない。AppleScript用語辞書に定義されている範囲のみである。

そのため、前述のGUI Scriptingによるメニューやボタンなどの強制操作が時と場合によって必要になる。この強制操作機能はOSのデフォルト設定ではオフになっているほか、アプリケーション/アプレット/Scriptごとに許可/禁止するようになっている。

UNIXコマンド[編集]

do shell scriptコマンドでBSD(UNIX)レイヤー上のコマンドを呼び出すことができる[10]。ただし、Terminal.app上とdo shell scriptコマンドでは設定されている環境変数が異なるため、Terminal.app上で実行できていた処理ができなくなる例が見られる。多くは、指定したコマンドにパスが通っていないこと、カレントディレクトリが異なることが原因。環境変数の内容を明示的に指定したり、利用コマンドをフルパスで表記することで回避可能(環境変数内容はenvコマンドを実行して確認が行える)。

リモートアプリケーション[編集]

Mac OS X標準装備の「リモートApple event」の機構を用いて、TCP/IPネットワーク(主にLAN)内の他のMac上のアプリケーションをコントロールできるようになっている。ただし、セキュリティ確保のためMac OS X標準装備のアプリケーションの多くは、この機能が禁止されているほか、OSのデフォルト設定ではリモートApple eventはオフになっている。

1台のMacでは処理が追いつかない場合、この機構を用いて複数台のMacに仕事を割り振り分散処理を行うケースも見られる。また、Mac上で稼働する仮想環境上でMac OS Xを動作させ、仮想環境との間での分散処理も可能。

Webサービス[編集]

SOAP、XML-RPCを呼び出すための命令が標準で装備されている(call soap、call xmlrpc)。Cocoaの機能を用いてRESTful APIを呼び出すことも可能[11]

これらのサービスが存在しないサイトに対しても、SafariをGUI Scriptingで強制的に操作することで、Webサービスにログインして必要な情報を取得するなどの処理が行われている。

iOSアプリケーション[編集]

iOS上でAppleScriptが動くわけでも、iOSのアプリケーションを直接コントロールできるわけでもないが、iCloudを経由して間接的にデータの変更を行える。たとえば、Mac OS X上のリマインダーを更新するとiOS上のリマインダーも更新される。これを利用して、iOS側に大量のデータを登録したい場合にMac上でAppleScriptなどによってデータを追加するといった方法が採られている。また、iPhoneとひもづけされたMacからAppleScriptを用いて電話をかけたりSMSメッセージを送信したりもできる[12]

各種フレームワーク[編集]

Mac OS X v10.10以降では、Objective-Cで開発されたサードパーティ製フレームワークをAppleScriptから直接呼び出すことが可能となっている。また、コンタクト(住所録)やカレンダーの情報をフレームワーク経由で検索したり操作することもできるようになった。

AppleScript Libraries[編集]

Mac OS X v10.9以降で、AppleScript自体をライブラリ化して再利用できるようになった。さらに、このライブラリにはAppleScript用語辞書を持たせることが可能なため、AppleScriptの命令語をライブラリによって拡張することが可能。

さまざまな実行環境[編集]

AppleScriptは中間コードに翻訳されて逐次実行されるが、さまざまな保存・実行環境(ランタイム環境)を持つため、実行環境によって動作が微妙に異なり、想定していた通りに動かないといったケースが散見される。

スクリプトエディタ上で実行[編集]

スクリプトエディタ上に記述して、スクリプトエディタ上で実行する形態。この際の実行環境はスクリプトエディタであり、途中でAppleScriptの実行を停止させたり、ログ表示させた内容を確認できる(ログ表示させると実行速度がいちじるしく低下する)。

アプレット/ドロップレットとして保存して実行[編集]

スクリプトエディタ上で記述して、アプリケーションとして保存、あるいはアプリケーションとして書き出したもの。この形態のものをアプレットと呼ぶ。アプレット実行時にはアプレット用のランタイム環境が用意されている。この環境で実行すると、on idleによるタイマー割り込み、ファイルやフォルダをドラッグ&ドロップ受信する機能、ハンドラの実行後に終了しない、プログレスバーの表示機能(Mac OS X v10.10より)などの機能が利用できる。ファイル/フォルダのドラッグ&ドロップを受け付けるアプレットをドロップレットと呼んで区別する(アイコンが異なる)が、ランタイム環境は同じである。

アプレット実行時にログ表示などの機能は利用できないため、この実行形態のままではバグの確認や修正が困難。スクリプトエディタ上で内容に問題がないことを確認しないとアプレット書き出しを行うべきではない。

Automator上で実行[編集]

Automatorのワークフロー記述の一部としてAppleScriptを使用することもできる。

Cocoa-AppleScript Appletとして保存して実行[編集]

Mac OS X v10.7で導入された。スクリプトエディタ上で「ファイル」>「テンプレートから新規作成」>「Cocoa-AppleScript Applet」を選択することで新規作成できる。AppleScriptObjCによるプログラムをスクリプトエディタ上で記述できるが、ユーザーインタフェースの作成が行えず、デバッグ機能も乏しい。

Xcode上でCocoa-AppleScript Appletとして作成してビルドして実行[編集]

Xcode上で「File」>「Project」>「Other」>「Cocoa-AppleScript」を呼び出すと作成される。一般的なCocoaアプリケーションをAppleScriptで開発する環境。一般的なCocoaアプリケーションに近いものが作れるが、一般的なCocoaアプリケーションを作成するための知識が必要とされる。Xcode内蔵のエディタ上で編集するAppleScriptは、文法要素に応じた構文色分け機能が利用できず、デバッグも行いにくい。複数のスクリプトファイルにプログラムを分割した場合のハンドラ呼び出し方法にクセがある。

スクリプトメニューに登録して実行[編集]

Mac OS Xのメニューバーから所定のフォルダ内のAppleScriptを実行できる、Mac OS X標準装備の「スクリプトメニュー」に登録・実行した場合の実行環境も、OSのバージョンに応じてさまざまな変更が加わってきた。Mac OS X v10.10からはosascriptコマンドで実行する実装になった。このため、スクリプトメニューから複数のAppleScriptを同時に実行させることが可能になったが、実行するScript同士で共通のアプリケーションにアクセスした場合のバッティングまでは面倒を見てくれない。

フォルダアクションに登録して実行[編集]

指定のフォルダ内容を数秒間隔で監視し、変更が加わるとAppleScriptの実行を行う機構。ランタイムの差異が問題を生むというよりも、このフォルダアクションの機構そのものがMac OS Xのバージョンによってはうまく動作していない(Mac OS X v10.10)ことが問題[13]

Terminalからosascriptコマンドで実行[編集]

OSバージョンによっては、display dialogなどのコマンドが利用できなかったが、Mac OS X v10.10以降はスクリプトエディタ上での実行にきわめて近いランタイム環境が提供されている。Terminal環境しか使いたくないユーザーが使っているケースが往々にしてあるため、スクリプトエディタ上で記述すれば発生しないような問題に直面するケースが見られる。実行環境の問題というよりも、利用者側の問題といえる。

アプリケーション内のScript実行機能で実行[編集]

FileMaker Proを外部からAppleScriptでコントロールするよりも、FileMaker Proスクリプトの「AppleScriptを実行」スクリプトステップ中にAppleScriptをコピー&ペーストで入れて実行する方が数倍高速に実行される。画面の再描画などを抑止するほか、高速実行するための仕組みを備えているものと見られている。

同様に、Adobe InDesignの「スクリプト」パレット中からAppleScriptを呼び出すことが出来、この際に画面の再描画を抑止できるため高速実行(おおよそ2倍)が可能となっている。ただし、Adobe InDesignについては大量のデータ処理時にクラッシュが発生するため、処理速度より安定稼働を重視すると外部からのコントロールも選択肢に入る。

Script Debugger上でデバッグ実行[編集]

AppleScript専用のサードパーティー統合開発環境といえるScript Debuggerでは、デバッグ時にAppleScript互換の「AppleScript Debugger 5」というAppleScriptとは別のOSA言語を実行することになる(数字の部分はScript Debuggerのバージョンによって異なる)。厳密にいえばAppleScriptそのものを実行するわけではないため、振る舞いが異なる箇所が出てくることは否定できない。ただし、以前(Classic Mac OS時代)に比べると純正AppleScript環境との互換性は大幅に高まっている。強力で便利な環境であるが、「デバッグ時以外はScript Debuggerを使うべきではない」という方針の開発現場もあるのは、この「互換性問題」ゆえである。

運用上、注意すべき項目[編集]

構文チェックが甘いので間違っている箇所を見つけにくい[編集]

スクリプトエディタ上でのコンパイル(実質的には構文チェック+中間コードへの置き換え)時には、AppleScriptの基本的な文法を外れなければ、それがたとえ実行できない命令の組み合わせであってもエラーにならない。実行時にエラーとなる。FinderのAppleScript用語辞書を見ていると「make new application」といったできそうもないプログラムを組めそうに見え、実際にFinderへのtellブロック内に記述するとコンパイルを通ってしまう。

tell application "Finder"
	make new application
end tell

実際には、アプリケーション側が想定している命令語の組み合わせは限定されたものである。また、想定された条件下によっては実行できるが、条件がそろわないと実行してもエラーになったり無意味な結果になるものもある。このため、アプリケーションが備えている機能を逸脱しない表記、アプリケーションの用語辞書で実現可能な記述パターンの情報を収集することには大いに意義がある(Appleが主催するメーリングリストのアーカイブの検索がこれに適している)。また、Scriptはこまめに実行して想定どおりの実行結果が得られているかを確認するとよい。

機能の分布が不均一[編集]

たとえば、printコマンドでプリンタを指定して書類を印刷する機能が存在していても、LAN内に存在するプリンタ名一覧を取得する機能はデフォルトでは用意されていない。同様に、テキストの音声読み上げを行うsayコマンドで音声キャラクタの名称を指定できるのに、現在システムにインストールされている音声名称の一覧を取得する機能が存在していない。このため、shell scriptやCocoaのサービスを呼び出して、取得する手段を別途用意する必要がある。

記述方法によって処理速度が大幅に変わる[編集]

何らかのオブジェクトの属性値を取得したい場合に、複数の属性値を何回かに分けて取得するよりもpropertiesでまとめて属性を取得した方が速いケースなどがある。アプリケーションをコントロールするために存在しているAppleScriptであるが、アプリケーションとの通信回数を減らすことが処理の高速化につながる。

アプリケーションの過度のローカライズにともなう互換性問題[編集]

iTunes、Keynote、Pages、NumbersなどApple純正アプリケーションに固有の問題が存在する。アプリケーションのローカライズをやりすぎて、AppleScript関連の機能までローカライズされてしまうことが多々ある。このため、海外で流布しているAppleScriptの、主にオブジェクト名称を英語名表記から日本語名表記に変更しないと日本語環境上では実行できない(エラーになる)ケースが存在する。

脚注[編集]

[ヘルプ]

関連項目[編集]

外部リンク[編集]