読者です 読者をやめる 読者になる 読者になる

blechmusikの日記

キー・カスタマイズ・ソフトウェア "DvorakJ" の覚え書きをはじめとして様々なことを書いています。

ファイルを一定時間毎に実行する repeat-exec.ahk を改良した

AutoHotkey

昨日公開したスクリプト*1には無駄な処理が多数あったので、つぎのように改良した。
第一に、ファイル名を柔軟に記述できるようにした。まず、ファイル名の直前に --program と記述しないようにした。そして、ファイルのパスとしてバックスラッシュの代わりにスラッシュを用いることができるようにした。
第二に、ファイルに任意の引数(最大で100弱)を渡せるようにした。
第三に、つぎのようなオプションを取るようにした。

--interval
ファイルを実行する間隔を秒で指定する
--times-executing
ファイルを実行する回数を指定する
--times-not-executing
ファイルをはじめの何回分実行しないかを指定する*2

これによりfenrirScan.exe を 30分毎に合計10回起動させるには、つぎのように記述する。

repeat-exec.exe fenrirScan.exe --interval 1800 --times-executing 10

ソースは以下の通りである。

;; repeat-exec.exe filename [args] [--interval seconds] [--times-executing times] [--times-not-executing times]

;; --interval 60 で 60秒間隔でファイルを実行
;; --interval 600 で 600秒(10分)間隔でファイルを実行
;; --interval の指定が無ければ 3600秒(60分)間隔でファイルを実行

;; --times-not-executing 1 で、はじめ1回分の時間はファイルを実行しない
;; --times-not-executing 10 で、はじめ10回分の時間はファイルを実行しない
;; --times-not-executing の指定が無ければファイルを常に実行する

;; --times-executing 0 で何回もファイルを実行する
;; --times-executing 1 で 1回ファイルを実行する
;; --times-executing 10 で 10回ファイルを実行する
;; --times-executing の指定が無ければ何回もファイルを実行する


file_info := []

;; 実行をスキップする回数
times_not_executing := 0
;; 実行する回数
times_executing := 0

sec  := 1000
min  := 60 * sec
hour := 60 * min
;; コマンドオプションが指定されていなければ、1時間毎にファイルを実行する
interval := hour

;; コマンドオプションの取得
arg_list := get_command_argument()

setting_interval := false
setting_times_executing := false
setting_times_not_executing := false
skip_item_index := 0

for i,v in arg_list {
    if (i = skip_item_index) {
        continue
    }

    if (("--interval" = v) and (false = setting_interval)){
        interval := arg_list[i+1] * sec
        skip_item_index := i + 1
        setting_interval := true
        
        continue
    }
    
    if (("--times-executing" = v) and (false = setting_times_executing)) {
        ;; 指定回数分ファイルを実行する
        times_executing := arg_list[i+1]
        skip_item_index := i + 1
        setting_executing := true
        
        continue
    }
    
    if (("--times-not-executing" = v) and (false = setting_times_not_executing)) {
        ;; はじめの任意の回数分ファイルの実行をスキップする
        times_not_executing := arg_list[i+1]
        skip_item_index := i + 1
        setting_times_not_executing := true
        
        continue
    }
    
    file_info.insert(v)
}

file_info[1] := slash_to_backslash(file_info[1])
filename := file_info[1]
file_info_text := array_to_text(file_info)

try {
    check_file_exist(filename)
} catch e {
    MsgBox,% "エラー: " filename " が見つかりません"
    ExitApp
}

Loop {
    tmptime := A_TickCount
    
    if (times_not_executing < A_Index){
        run,% file_info_text
    }
    
    if (A_Index = times_executing){
        Break
    }
    
    elapsed_time := A_TickCount - tmptime
    sleep, % interval - elapsed_time
}

return


check_file_exist(file) {
    if (FileExist(file) = ""){
        throw Exception("Fail", -1)
    }
}

get_command_argument(){
    global
    local arg_list := []
    
    Loop,100
    {
        if ("" != Trim(%A_Index%)){
            arg_list.insert(%A_Index%)
        }
    }
    
    return arg_list
}

array_to_text(arr){
    str := ""
    
    for i,v in arr
    {
        str .= v " "
    }
    
    return str
}

slash_to_backslash(filename){
    return RegExReplace(filename, "/", "\")
}

後日追記:改良し損ねていた点を修正した。