ファイルに変更を与える際、すでにファイルが掴まれていたら何度もチャレンジする
ファイルを書き込もうとしたら、他のプロセスなどにそのファイルが掴まれていて、書き込みに失敗することがある。このとき成功するまで何度もチャレンジしたい。
Dim fso As New FileSystemObject Dim t As TextStream Do On Error Resume Next Set t = fso.CreateTextFile("hoge.txt", True, False) On Error GoTo 0 If Not t Is Nothing Then Exit Do Sleep 500 Loop t.Write "hello, world!" t.Close Set t = Nothing
こんな感じでやった。ファイルが掴まれている場合、fso.CreateTextFileのところでエラーになるので、そこだけOn Error Resume Nextする。それで、あとでtにちゃんと結果が入ったかどうかを調べる。ダメだったらループしてもう一度やってみる。うまくいったらループを抜ける。
Sleep 500のところは、再チャレンジする前に0.5秒ほどお休みするために書いた。これがないとものすごい早さで再チャレンジして、全体が重くなる。Sleep関数は通常のVBには無いのでWindows APIを呼び出している。定義は以下。
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
再チャレンジの回数をカウントしておいて、20回試してダメだったらエラーにしてアプリを落とすとか、そういう感じにするとさらに良いと思う。
今回のはVB6だけど、FileSystemObjectやOn Error Resume Nextしか使ってないのでVBScriptでも書ける(Sleepは無理)。VB.NETなら、普通にTry〜Catchで書ける。
失敗例 : On Error GoToを使う
最初、On Error GoToを使おうとして、以下のようなコードを書いた。
Dim fso As New FileSystemObject Dim t As TextStream On Error GoTo catch try: Set t = fso.CreateTextFile("hoge.txt", True, False) t.Write "hello, world!" t.Close Set t = Nothing Exit Sub catch: Sleep 500 GoTo try
これは失敗だった。On Error GoToでジャンプすると、そのプロシージャ内ではもう一度On Error GoToすることはできないらしい。
そこで最後のGoTo tryのところをResume tryって書けばいけそうだと思ったとき、だったら最初からOn Error Resume Nextすりゃいいやということに気付いて、冒頭のコードを書いたわけだ。