何故かAppleScriptが動かない時はactivateしたら良いよという話 

はてなブックマーク - 何故かAppleScriptが動かない時はactivateしたら良いよという話
Bookmark this on Delicious

覚えたばかりのAppleScriptが動かなくて、ハマり倒したのでメモしておきます。まず動かなかったのは以下のコードで、やろうとしてるのは一番新しい送信ボックス中のメールに返信する形で新しいメールを作って件名と本文に適当な文字列を設定すると言うことです。単純ですね。

on run
  tell application "Mail"
       set last_msg to the first message of sent mailbox
       set reply_msg to reply last_msg with opening window
       tell reply_msg
            set subject to "replied"
            set content to "this is replied message"
       end tell
  end tell
end run

パッと見は動きそうなのですが、実行するとsubjectの設定でAppleEvent handler failedという謎のエラーが出ます。replyではなくて新しくメールを作った場合は動作するので、さっぱり原因が予想できず自己解決できませんでした。

そこでstackoverflowに質問すると、OSX 10.5.xのMail.appはバギーだからOSX 10.6.xにした方が良いよと言われたので、なるほどと思い従ってみたのですが今度はcontentのセットがエラーは出ないものの失敗します。SnowLeopardでも駄目やんと言うと、本家のapplescript-usersに聞いてくれと言われたので再度質問してみると、Piyomaruさんにdelayを使うと良いよと教えてもらいました。コード的には以下になりまして、これはばっちり動作します。要は各処理がちゃんとブロッキングされていないので、sleepして調節するべしと言う事です。ただ動くのですが、これAppleScriptマジかよと疑いたくなる内容ですね。

on run
  tell application "Mail"
       set last_msg to the first message of sent mailbox
       set reply_msg to reply last_msg with opening window
	   delay 2.0
       tell reply_msg
            set subject to "replied"
			delay 1.0
            set content to "this is replied message"
       end tell
  end tell
end run

マシンのスペックによってこの程度のスクリプトが動いたり動かなかったりするのかと思って萎えていたのですが、@semwebさんとの会話でactivateしたら動くんじゃね?と言うことになりまして試してみるとこれがばっちり動作しました。結果のコードは以下になりまして、処理前にactivateを入れているだけです。

on run
  tell application "Mail"
  	   activate
       set last_msg to the first message of sent mailbox
       set reply_msg to reply last_msg with opening window
       tell reply_msg
            set subject to "replied"
            set content to "this is replied message"
       end tell
  end tell
end run

Cocoaを理解していないので正確な事は分からないのですが、バックグラウンドで走っているプロセス上の処理が、ごにょごにょされた結果スクリプトの各行がブロッキングじゃ無くなるとかそういう雰囲気です。なんとなくこれはMail.appに限らない話だと思われるので、AppleScriptが何故か動かない時はとりあえずactivateしておけば良いと思います。これはpy-appscript等のラッパーを使っていても同様です。

from appscript import *
 
mailapp = app('Mail')
mailapp.activate()
 
msg = mailapp.sent_mailbox.messages.first
reply_msg = mailapp.reply(msg, opening_window=True)
 
reply_msg.subject.set('replied message')
reply_msg.content.set('some content')

「activateを1行入れる」にたどり着くまでに結局1週間かかりまして、もっと問題解決プロセスを高速化しないとあっという間に死にそうだなぁというこの頃です。

関連する記事

タグ: , ,

コメントをどうぞ