[Mojave以降] AppleScript製アプリのアクセス許可のダイアログが毎回出るのを防ぐ

原因と症状

Mojave以降のmacでは、アプリによっては以下のようなダイアログが起動のたびに出てしまいます。

「"hoge"が"fuga"を制御するアクセスを要求しています。制限を許可すると、"fuga"の書類やデータにアクセスしたり、そのアプリケーション内で操作を実行したりできるようになります。」

こういった問題が起こるのはAppleScript製アプリだけのようで

  • "スクリプトエディタ.app"を使ったAppleScript製アプリ
  • iTunesなど他アプリを制御する箇所がある
  • 変数など起動するたびに変わる要素がコード内にある

以上の条件をすべて満たすと、起動するたびにアプリ内のデータが変わるので、セキュリティ機構には別アプリと見做され、毎回アクセス許可のダイアログが表示されてしまいます。

AppleScript製アプリを多数公開してきた身としてはとても困る問題です。

例えば以下のような簡素なアプリでも起動のたびに毎回アクセス許可のダイアログが出ます。

set x to current date

tell application "iTunes"
    display dialog x as text
end tell

解決策

Xcodeを利用してちゃんとしたアプリを作る

"スクリプトエディタ.app"だけを使ったお手軽アプリは、変数の値などもすべてアプリ内に保存してしまいます。

Xcodeを利用してちゃんとしたアプリを作れば、アクセス要求のダイアログは初回しか出ません。

ただ、めんどくさいのでこの解決策は個人的にはパス。

ユーザ定義のスクリプトオブジェクトを読み込む

script MyScript
    -- ここに処理を書く
end script

on run
    local tempScript
        copy MyScript to tempScript
    run tempScript
end run

「script 〜 end script」で囲まれた部分がユーザ定義のスクリプトオブジェクト。

これを用意しておいた空のローカル変数にコピーして、コピーしたスクリプトオブジェクトを実行します。

こうするとアプリ本体にその時のステートを保存するのを避けられるみたいです。

ただこのやり方だとpropertyを利用した、設定の保存もできなくなるので辛い。

ユーザ定義のスクリプトオブジェクトを読み込む ver.2



(*
plist handler.applescript
https://github.com/veadar/AppleScript/blob/master/plist%20handler.applescript
*)

script MyScript
    -- ここに処理を書く
    
    set bID to "com.yourcompanys.name" --example
    
    if plistRead(bID, "setting") is "" then
        --settingの初期値
        plistWrite(bID, "setting", 1)
    end if
    
    set hoge to plistRead(bID, "setting")
    
    tell application "iTunes"
        display dialog hoge
    end tell
    
    set hoge to hoge + 1
    --settingの上書き
    plistWrite(bID, "setting", hoge)
end script
on run
    
    local tempScript
    copy MyScript to tempScript
    run tempScript
end run

on plistWrite(bID, theKey, theValue)
    set shellText to "defaults write " & bID & " '" & theKey & "' -string '" & theValue & "'"
    do shell script shellText
end plistWrite

on plistRead(bID, theKey)
    set shellText to "defaults read " & bID & " '" & theKey & "'  | native2ascii -reverse -encoding UTF-8"
    do shell script shellText
end plistRead

コードは長くなりましたが、やっていることは一個前とほとんど同じで、設定をアプリ固有のplistに保存して呼び出しているだけです。

propertyが使えなくなるだけで、ここまで長くなってしまうのは辛い。

他アプリを制御の部分を別アプリに書き出して読み込む

「起動するたびにアプリ内のデータが変わる」の部分をどうにかしようと、様々な方法を試しましたがすべてダメでした。

  • plistファイルに書き出して読み込む
  • テンポラリファイルから読み込む
  • osascriptコマンドでベタ書きしたスクリプトを読み込む
  • load scriptで別スクリプトを読み込む

これでわかったことは、コード内の変数(load scriptなどで読み込んだスクリプト内であっても!)に違うデータが入るだけで、別アプリとして見做されるということです。

ならばコロンブスの卵的な発想で、「iTunesなど他アプリを制御する箇所がある」の部分をコードから排除する方向で無理くりなんとかする方法を考えました。

他アプリを制御する部分は別アプリとして書き出して、それをメインスクリプト内でopenコマンドから呼び出す感じです。

このやり方はpropertyを利用した設定の保存ができますが、別アプリ制御部分に変数の引渡しができません。

参考サイト