ぺんちゃん日記

食と歴史と IT と。 Web の旅人ぺんじろうが好奇心赴くままに彷徨います 。

【AutoHotkey】まさかの処理でSleep入れないと動かない

f:id:yasushiito:20190401185150p:plain

これまで書いてきたスクリプトが動いたり動かなかったりします。
「おかしいなあ、このスクリプト以前は動いてたと思うんだけどいつのまにか動かなくなってるや」みたいなことがあるんです。

AutoHotkeyは自動化といっても手作業でやるべきところを素早く操作させているだけなので、あまりにも早すぎると期待通りに動きません。
例えばウィンドウを切り替えてクリップボードにコピペするときも待ち時間なしで実行してしまうとウィンドウを切り替えている間にキーボード送信してしまってメッセージを蹴られたりします。
AutoHotkeyをやっている人にとっては常識すぎるので通常はスリープコマンドで少しずつ間隔を空けながら操作させていきます。
まあところがですよ。
常識的に考えたこんなところにスリープはいらんだろうというところで引っかかったりすることがあります。
と言うかありました。
例えばこの辺の処理なんですけど。

#=::
    editor := 0
    work := 0
    WinGet, windows, list
    loop ,%windows%
    {
        idstr := "ahk_id " . windows%A_Index%
        WinGetTitle,title,%idstr%
        pos := RegExMatch(title,"- Google Chrome$")
        if pos > 0
        {
            pos := RegExMatch(title,"音声入力用")
            if pos > 0
            {
                WinGet,editor,ID,%idstr%
            }
            else
            {
                WinGet,work,ID,%idstr%
            }
        }
    }
    If (editor = 0) return
    If (work = 0) return
    WinActivate,ahk_id %work%

ちょっと長い処理ですが、ウィンドウ一覧から必要なウィンドウの ID を変数に取り込んで、その中の一つをアクティブにしています。
着目すべき場所はここ 。

    If (editor = 0) return
    If (work = 0) return
    WinActivate,ahk_id %work%

ここ以前は内部的な処理ばかりなのでユーザの操作によって処理が遅れるなんてことはないはずです 。
ウィンドウの ID はすでに取得してしまっているのでアクティブウィンドウの切り替えに間を持たせる必要なんてないと思うじゃないですか。
しかしこれ動かない時があるんですよ。
こんな感じにすれば動きます。

    If (editor = 0) return
    If (work = 0) return
    Sleep 500         ; <----------------
    WinActivate,ahk_id %work%

ユーザが操作する前の処理にもスリープがいるとは思わなかった 。

まとめ。

ユーザの操作の間だけでなく、最初と最後にも入れましょう。
少々効率は落ちますがスリープは過剰なまでに入れた方が良さそうです。
スクリプト実行ミスが発生すると大切なウインドウに訳の分からない操作を突っ込みかねないですからね。