あまつぶ

3.24 7:30 【スクリプトを実行する】

 QT-Qに「スクリプト」メニューを追加。「スクリプト」フォルダにコンパイル済みスクリプトを入れておくとメニューから実行することができるというもの。そんなに劇的に使い勝手が向上するなんてことはないと思うけど、使いようによっては面白いかも知れない。通常はQT-Qの制御のために使うんだろうけどもちろん他のアプリケーションを制御することもできるから。例えばフロントウィンドウの内容をコピーしてclip2gifでGIFで保存してしまうなんてこともできるはず。要は自分で好きなようにカスタマイズできるところがポイントなわけ。
 スクリプトの実行はOSAのルーチンを使う。コンパイル済みのスクリプトファイルを開いてスクリプトを取り出してそれをOSALoadExecuteで実行してやるだけ。最初「取り出して」の部分をどうやるのかわからなかったけど、ちょっとIMを読んであとは勘でやってみたらあっさり成功。意外と簡単だったな(運がよかっただけかも知れないけど(笑))。あと、記録と保存ができるようになればAppleScriptに関する一通りのことができたことになるのかな。QT-Qでそこまでやる必要があるかどうかはともかく。
 コンパイル済みのスクリプトファイルはファイルタイプが'osas'で、'scpt'リソースにスクリプトのデータが入っている。IDはスクリプト編集プログラムで作ったものはすべて128だったので128だと思っておけばいいのかな。細かいことはIMを読むべきかな。インデックスで1番目ならほぼ確実かも知れないけど。読み込んだデータをリソースから切り離して(DetachResource)それをデータに持ち、タイプがtypeOSAGenericStorageのデスクリプタを作成する。あとはOSALoadExecuteで実行(当然ながら実行の前にスクリプティングコンポーネントを開いておく)。スクリプトの実行でエラーが起こったらerrOSAScriptErrorが返ってくるからOSAScriptErrorでエラーの内容を取り出し(セレクタkOSAErrorMessageを使用)、ダイアログに表示してやる。最後に使用したデータを破棄すると。

 流れがわかったところでひさしぶりにソースを掲載。

/* スクリプトファイルを実行する */
void ExecuteScriptFile(FSSpec *scriptFile)
{
	OSErr		err;
	AEDesc		scriptData;
	OSAID		result;
	Handle		resHandle;
	short		refNum;
	
	/* まずスクリプトファイルを開く */
	refNum=FSpOpenResFile(scriptFile,fsRdPerm);
	if (refNum<0)
	{
		ErrorAlert("\pスクリプトファイルを開くことができませんでした");
		return;
	}
	
	/* 'scpt'リソースを取り出す */
	resHandle=Get1Resource('scpt',128);
	if (resHandle==nil)
	{
		CloseResFile(refNum);
		ErrorAlert("\pスクリプトが存在しません");
		return;
	}
	DetachResource(resHandle);
	CloseResFile(refNum);
	
	/* デスクリプタに値を設定する */
	scriptData.descriptorType=typeOSAGenericStorage;
	scriptData.dataHandle=resHandle;
	
	/* スクリプトを実行する */
	err=OSALoadExecute(gGenericSC,&scriptData,
				kOSANullScript,kOSAModeNull,&result);
	if (err==errOSAScriptError)
	{
		AEDesc	errorDesc={typeNull,NULL};
		Str255	errorStr;
		
		/* スクリプトの実行でエラーが起こったらメッセージを表示 */
		err=OSAScriptError(gGenericSC,kOSAErrorMessage,
				typeChar,&errorDesc);
		err=GetPStringFromDescriptor(&errorDesc,errorStr);
		if (err==noErr)
			ErrorAlert(errorStr);
		
		AEDisposeDesc(&errorDesc);
	}
	
	err=OSADispose(gGenericSC,result);
	err=AEDisposeDesc(&scriptData);
}


scriptFileで指定されたスクリプトを実行する。2つだけToolboxでないルーチンを使っているので少し解説。ErrorAlertというのは、エラー報告ダイアログを表示するルーチン。もう一つGetPStringFromDescriptorというのを呼んでいるが、これはデスクリプタのデータからパスカル文字列を取り出すルーチン。また、gGenericSCというのはスクリプティングコンポーネントのインスタンスを保存してあるグローバル変数。アプリケーション起動時に初期化してある。
 ちょっとエラー処理が手抜きなので実際に使う時はもう少しちゃんとしないとまずいだろうけど大筋はこんな形。たったこれだけのソースコードでコンパイル済みスクリプトを実行できるのだからおもしろい。コンパイルされていないスクリプトの場合なら実行の前にコンパイルしてやるだけだからこれもそれほど複雑ではない。Cで「オブジェクトスペシファイアを構築して……」なんてやるのに比べたらかなり楽だ。実行速度は遅いけど、簡単にカスタマイズできることを考えたら使ってみない手はないと思う。

 全然関係ないけど、QT-Qのソースファイルがだんだんすごいことになってきた。最初はこんな複雑なプログラムになる予定はなかったので1つのファイルで作っていて、未だにそのまま1つのファイルになっている。ソースファイルの容量をチェックしたらなんと164k。行数も6600行を越えてしまったしそろそろ分割しないといけないなぁ。まあ完成も近いからこのまま気合いでいくって手もあるけど(笑)。

to March 23, 1999 ↑ to March index → to March 25, 1999