JXAでアプリケーションを指定してStandard Additions
のメソッドを使おうとすると頻繁に以下のエラーが出る。
var finder = Application("Finder");
finder.includeStandardAdditions = true;
finder.doShellScript("date");
//!! Error on line 1: Error: A privilege violation occurred.
この場合currentApplication
を使えばたぶん大体いける。
var app = Application.currentApplication();
app.includeStandardAdditions = true;
app.doShellScript("date");
//=> "2015年 2月25日 水曜日 17時16分28秒 JST"
currentApplication
はスクリプトを実行しているアプリケーションを取得するメソッド。
Script Editorから実行していればScript Editor。
Terminalから実行していればTerminal...じゃなくてosascript
コマンド。
Terminalが直接実行してるわけじゃないので。
他にも、例えば
CotEditorはユーザーが作ったスクリプトを利用できる。
そこで実行した場合のcurrentApplication
はCot Editor。
osascriptを参照した際のwarning
warning: failed to get scripting definition from /usr/bin/osascript; it may not be scriptable.
と毎回出るけど「osascriptには.sdef
ファイルが無いから、スクリプトで操作できないと思うよ」ってだけ。
osascript自体じゃなくStandard Additions
のメソッドを使うだけだから問題無し。のはず。
osascriptの参照から名前を得ようとして.name()
とかやったらエラー出るので注意。
ていうかこれ不安になるだけだから表示しないでほしい。いややっぱ必要か。
スクリプトメニューから実行した場合のcurrentApplication
Script Editorみたいな分かり易いものならいいけど、スクリプトメニューから実行した場合は何が呼ばれるのか。
currentApplication
は多用するから、得体の知れないまま使うとモヤモヤする。
AppleScriptと違って、明示的にStandard Additions
を有効にしないと駄目だし気になったので調べた。
スクリプトメニューについて
スクリプトエディタの設定からスクリプトメニューを有効にするとメニューにアイコンが追加される。
スクリプトを~/Library/Scripts/
に入れるとそのメニューに表示される。
コンパイル済みスクリプト(.scpt
)にすればいつでもどこでもワンクリックで実行できる。
ちなみにScript Editorを経由しないでも設定変更可能。
var app = Application("AppleScript Utility");
// 確認
app.scriptMenuEnabled();
//=> true / false
// 有効にする
app.scriptMenuEnabled = true;
スクリプトメニューの「currentApplication」
これを調べるスクリプトをJXAで書くと難しい。
ていうか結局、分からなかった。
AppleScriptだと簡単だった。
display dialog (path to current application)'s POSIX path
/Applications/Utilities/Script Editor.app/
/usr/bin/osascript
普通にosascript
だった。
蛇足
予想では専用のアプリケーションがあるのか、最前面のアプリが使われるのか、Finderなのかとか考えてた。
昔はこれだったらしい。今は存在しない。(参考:MacWiki)
/System/Library/CoreServices/AppleScript Runner.app
スクリプトメニューでエラーが発生した場合
何も起こらない。何も通知されない。
途中で単に実行が停止されるので注意。
ちゃんと try...catch
すればだいじょぶ。
コンソール.appにエラーのヒントが残ってるかもしれない。
蛇足2
上に書いたけどcurrentApplication
の名前はAppleScriptで一行で得ることが出来た。
JXAで何とかしようとしてた(けど出来なかった)コードをここで供養する。
var app = Application.currentApplication();
app.includeStandardAdditions = true;
var str = Automation.getDisplayString(app);
// これじゃたぶん意味ない。(osascriptで実行してるじゃん)
//msg = app.doShellScript('osascript -l JavaScript -e "Application.currentApplication()" 2>&1 1> /dev/null | cat');
//str += "\n" + msg;
try { // try..catchしとかないとエラー出たら無言でアプレット消える
str += "\n\nproperties: " + Automation.getDisplayString(Object.getOwnPropertyNames(app));
str += "\nname: " + app.name(); //osascriptから.name()とか呼んだらエラー出る
str += "\n\n" + JSON.stringify(app.properties(), null, " ");
} catch(e){
str += "\n\n" + e.toString();
}
app.displayDialog(str);
Script Editorで実行した場合のダイアログ。
Application.currentApplication()
properties: ["__private__"]
name: Script Editor
{
"frontmost": true,
"class": "application",
"name": "Script Editor",
"version": "2.7"
}
スクリプトメニューから実行した場合のダイアログ。
Application.currentApplication()
properties: ["__private__"]
Error: Message not understood.
JXAのStandard AddisionsにもpathTo
はある。
けどcurrent application
を文字列で渡したりcurrentApplicationをそのまま渡してもパスを得られなかった。
JXAでパスを得る方法があったなら知ってる方は教えて下さい。