JXAの「Error: A privilege violation occurred」の回避

  • 8
    Like
  • 1
    Comment
More than 1 year has passed since last update.

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)にすればいつでもどこでもワンクリックで実行できる。

menu.jpg

ちなみにScript Editorを経由しないでも設定変更可能。

var app = Application("AppleScript Utility");

// 確認
app.scriptMenuEnabled();
//=> true / false

// 有効にする
app.scriptMenuEnabled = true;

スクリプトメニューの「currentApplication」

これを調べるスクリプトをJXAで書くと難しい。
ていうか結局、分からなかった。

AppleScriptだと簡単だった。

where_is_current_app.scpt
display dialog (path to current application)'s POSIX path

Script Editorで実行した場合。
editor.jpg

/Applications/Utilities/Script Editor.app/

スクリプトメニューから実行した場合。
menu_.jpg

/usr/bin/osascript

普通にosascriptだった。

蛇足

予想では専用のアプリケーションがあるのか、最前面のアプリが使われるのか、Finderなのかとか考えてた。

昔はこれだったらしい。今は存在しない。(参考:MacWiki)
/System/Library/CoreServices/AppleScript Runner.app

スクリプトメニューでエラーが発生した場合

何も起こらない。何も通知されない。
途中で単に実行が停止されるので注意。
ちゃんと try...catch すればだいじょぶ。

コンソール.appにエラーのヒントが残ってるかもしれない。

スクリーンショット 2015-02-25 18.55.29.png

蛇足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でパスを得る方法があったなら知ってる方は教えて下さい。

参考