オープンソースのCocoa Frameworkをgithubなどからダウンロードしてビルドし、AppleScriptから実行することは日常的に行なっています。
ただし、これはmacOS 10.14で~/Library/Frameworksから読み込んで実行することが、スクリプトエディタ上では禁止、Script Debuggerでのみ可能という状況です。
macOS標準添付のFrameworkの多くは、/System/Library/Frameworks以下に(若干の例外はあれど)配置されていることが期待されます。
スクリプトエディタ上で実行するScriptについては、macOSデフォルトインストールされているAppleのFrameworkしか呼び出せない状況です。
そこで、/Library/Frameworksあたりに入れたFrameworkを強制的に呼び出せないかと実験してみたものが、これです。
choose fileで指定したFrameworkを強制的に読み込んで実行するテストを行なってみました。結果からいえば、Script Debugger上では実行できるのですが、スクリプトエディタではloadが行えず、エラーになりました。
結論:残念!
もともと、ホームディレクトリ以下のバイナリを呼び出すことをSIPで禁止したいというセキュリティ上のポリシーによって、macOS 10.14以降ではmacOS標準装備のスクリプトエディタが影響を受けました。
Script Debuggerでこの点は補われていたわけですが、AppleScriptから/Library/FrameworkにインストールしたFrameworkを呼び出すことを許可していただきたいところです。/Library/Frameworkなら、ホームディレクトリ以下ではないし、管理者権限がないとFrameworkのインストールもできないため、サードパーティのFrameworkのインストール先としては妥当です。何らかの悪意をもったソフトウェアがFrameworkを勝手にインストールする危険性も低いことでしょう。
AppleScript名:Framerokを任意のパスからloadして実行するじっけん.scptd |
— – Created by: Takaaki Naganoya – Created on: 2025/01/29 — – Copyright © 2025 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use scripting additions set fPath to POSIX path of (choose file) loadAndExecuteFramework(fPath, "SFPSDWriter") of me on loadAndExecuteFramework(frameworkPath, functionName) — Frameworkのパスをチェック (* if frameworkPath does not start with "/Library/" then display dialog "Error: Framework path must be inside /Library/" return end if *) — Frameworkをロード set frameworkNSURL to current application’s NSURL’s fileURLWithPath:frameworkPath set bundle to current application’s NSBundle’s bundleWithURL:frameworkNSURL if bundle is missing value then display dialog "Error: Failed to load framework at " & frameworkPath return end if — Frameworkのクラスをロード set isLoaded to bundle’s load() if isLoaded is false then display dialog "Error: Failed to load framework" return end if — クラスを取得 set className to current application’s NSClassFromString(functionName) if className is missing value then display dialog "Error: Function ’" & functionName & "’ not found" return end if log className — メソッドを実行(クラスメソッドとして想定) try className’s performSelector:"execute" display dialog "Function ’" & functionName & "’ executed successfully." on error errMsg display dialog "Error executing function: " & errMsg end try end loadAndExecuteFramework |