【テクニカル・上級編】【ファイル排他検知】他プロセスによるファイル使用(ロック状態)を安全に判定する試行関数 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

VBScriptを掌握する極限の知見:ファイル排他ロック判定の「正しい」実装

レガシーシステムの維持管理において、もっとも避けるべきは「予期せぬ実行時エラーによるプロセスの不完全終了」である。特に共有ファイルサーバー上のExcelファイルや、バックグラウンド処理中のログファイルを扱う際、ファイルを握りつぶしてクラッシュするスクリプトは、業務自動化の敵だ。

今日は、VBScriptにおける「ファイル排他ロック」の判定について、初学者が陥る罠を回避し、堅牢なアーキテクチャを構築するための極意を伝授する。

1. なぜ「FileSystemObject」のOpenTextFileなのか

多くのエンジニアは、`Scripting.FileSystemObject` の `FileExists` や `GetFile` を確認するが、これらは「ファイルの存在」を証明するだけで、「使用権(アクセス権)」については沈黙を守る。

他プロセスによる排他ロックを検知する唯一の泥臭い、しかし確実な方法は、「排他モードでファイルを開こうと試み、OSから拒絶されるかどうか」を判定することだ。

核心となる実装コード

以下のコードは、エラーハンドリングを最小のスコープで完結させ、オブジェクトのメモリ解放までを完璧に制御した「試行関数」である。

‘ @brief ファイルが他プロセスによってロックされているか判定する
‘ @param filePath 検査対象のフルパス
‘ @return Boolean (True: ロック中/アクセス不可, False: 使用可能)
Function IsFileLocked(filePath)
Dim fso, ts
Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ 存在しないファイルを対象にするリスクを排除
If Not fso.FileExists(filePath) Then
IsFileLocked = False
Set fso = Nothing
Exit Function
End If

On Error Resume Next ‘ エラーをトラップする(ここが要)

‘ ForAppending かつ IOMode 8 を指定して開くことで
‘ 書き込み権限と排他制御の競合を誘発させる
Set ts = fso.OpenTextFile(filePath, 8, False)

If Err.Number <> 0 Then
‘ エラーが発生した=他プロセスが排他ロックを保持している
IsFileLocked = True
Err.Clear
Else
‘ 成功した場合は即座に閉じる(これが重要)
ts.Close
IsFileLocked = False
End If

On Error Goto 0 ‘ エラーハンドリングを解除

‘ オブジェクトの明示的解放(メモリリークの温床を断つ)
Set ts = Nothing
Set fso = Nothing
End Function

2. アーキテクトの視点:なぜこれが「極限」なのか

オブジェクトライフサイクルの管理

VBScriptのガベージコレクションを信用してはいけない。`Set obj = Nothing` を省略するエンジニアを私は認めない。特にループ処理内でこの判定を繰り返す場合、解放漏れは即座にメモリ枯渇(メモリリーク)を招く。このコードでは、`If` の分岐ごとに確実にオブジェクトを破棄する設計としている。

`On Error Resume Next` の正しい「汚し方」

初心者はスクリプト全体を `On Error Resume Next` で囲うが、それは論外だ。エラーの発生場所を特定できなくなり、デバッグ不能なコードが完成する。上記のコードのように、「クリティカルな1行」の直前で有効化し、直後に解除するのが、プロフェッショナルの作法である。

なぜ `OpenTextFile` なのか

Windows APIの `CreateFile` を呼び出す方法(`kernel32.dll` の `CreateFileW` 等)もあるが、VBScriptで `ADODB.Stream` や API呼び出しを多用すると、環境依存のバグが激増する。保守性を極めるならば、標準ライブラリ `Scripting.FileSystemObject` で完結させるのが最もリスクが低い。

3. 実務への応用:待機ロジックの構築

この関数を単体で使うことは少ないだろう。実務では「ロックが解除されるまで待機する」ロジックと組み合わせるのが定石だ。

Dim retryCount : retryCount = 0
Do While IsFileLocked(“C:\Target\Data.xlsx”)
If retryCount > 10 Then
WScript.Echo “タイムアウト:ロックが解除されません”
WScript.Quit 1
End If
WScript.Sleep 1000 ‘ 1秒待機
retryCount = retryCount + 1
Loop

‘ ここに本来の処理を記述

最後に:レガシーを愛し、極めること

VBScriptは「古い技術」と切り捨てるのは簡単だ。しかし、この枯れた技術が、Windowsの深層でいまだにミッションクリティカルな業務を支えている。

「なぜエラーが起きるのか」という問いに対し、API仕様とOSの挙動から逆算して最適解を導き出す。この姿勢こそが、自動化エンジニアとしての真価である。コードは、動けばいいというものではない。「壊れないこと」に魂を込めよ。

次の現場で、このロジックが貴殿のスクリプトを救う盾となることを願う。

タイトルとURLをコピーしました