Automator のアクションで子プロセスを走らせたとき、子プロセスを管理するのはアクション側の責任になります。Automator のワークフローはユーザの操作によって停止することがありますが、その場合、子プロセスを終了させるのは、アクションの実装者の責任です。
AppleScriptObjC で自作アクションを書けますが、ナイーブに do shell script を使って子プロセスを起動させると、停止させる術がありません。NSTask を使って自分で管理するのが良さそうです。
ユーザの停止操作によって、AMAction から継承した stop メソッドが呼ばれますので、そこで動いている子プロセスを停止させます。テンプレートとしては、こんな感じでしょうか。
script my_Automator_Action property parent : class "AMBundleAction" property NSTask : class "NSTask" property NSFileHandle : class "NSFileHandle" property task : missing value -- @override on runWithInput_fromAction_error_(input, anAction, errorRef) ... set command to POSIX Path of "..." set args to {} set the end of args to "argument 1" set the end of args to "argument 2" ... my runExternalTask(command, args) ... end runWithInput_fromAction_error_ -- @override on |stop|() if task is not missing value then task's terminate() end if end |stop| -- Instead of 'do shell script', use this method to prepare for abortion by user operations. on runExternalTask(command, args) set nulldev to NSFileHandle's fileHandleWithNullDevice() set task to (NSTask's alloc)'s init() task's setLaunchPath_(command) task's setArguments_(args) task's setStandardInput_(nulldev) task's setStandardOutput_(nulldev) task's setStandardError_(nulldev) task's |launch|() task's waitUntilExit() task's autorelease() set task to missing value end runExternalTask end script
気付いた点をいくつか。
- NSTask の setArguments: は NSArray を受け取ることになっていますが、以下のようにAppleScript の文字列のリストをそのまま渡しても問題ないようです。ただし、リストの中に数値などが入っていた場合、自動的に文字列に変換してくれず、エラーになります。
- 標準出力と標準エラー出力を /dev/null へつないでおかないと、コンソールに全部出てしまいます。
- do shell script は一旦シェルを経由するので、リダイレクトやパイプの指定ができます。同様のことを行うには、NSPipe や NSFileHandle 等を使って自力でやるか、一旦シェルを呼び出すようにします。
- do shell script は標準出力の内容を戻り値として取得できますが、NSPipe を使って自力で取得する必要があります。
0 件のコメント:
コメントを投稿