こんにちは!VBScriptの海原を航海する開発者の皆さん、順調ですか?
業務の自動化を進めていくと、テキストファイルやログファイルをVBScriptから書き出す処理を嫌というほど書くことになりますよね。`TextStream`オブジェクトを使ってファイルをOpenし、ガリガリと書き込んでいく……。あれ、シンプルでとても便利です。
しかし、実務でこのファイル書き込みを大量に行うシステムや、絶対にデータを消してはいけない重要ファイル(設定ファイルやマスターデータなど)を扱うようになると、ある「悪夢」に直面します。
「ファイル書き込みの途中で、突然PCがシャットダウンした・エラーでスクリプトが強制終了した。結果、ファイルの中身が0バイトの空っぽになったり、途中で途切れたゴミデータになって復旧不能になった……」
……どうでしょう、背筋が寒くなりませんでしたか?
今回は、そんな現場のエンジニアを絶望の底に突き落とす「ファイル破損」の恐怖から完全に身を守るための、プロフェッショナルな技術「アトミック書き換え(一時作成+瞬時置換)パターン」を伝授します。
ここをクリアすれば、あなたの書くVBScriptは「おもちゃのマクロ」から「堅牢なエンタープライズ・スクリプト」へと進化します。一緒に本質をマスターしていきましょう!
—
1. なぜ、通常のファイル書き込みは危険なのか?
まずは、私たちが普段やりがちな「危ういコード」を思い出してください。FSO(FileSystemObject)を使ってファイルを開き、上書き保存するコードですね。
‘ 【危険なアンチパターン】
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ ForWriting (2) で開いた瞬間、既存ファイルの内容は「0バイト」にクリアされます!
Set ts = fso.OpenTextFile(“C:\Data\config.ini”, 2, True)
ts.WriteLine “SettingA=100”
‘ — 万が一、この瞬間に停電やエラーが発生したら……? —
ts.WriteLine “SettingB=200”
ts.Close
FSOの`OpenTextFile`メソッドで「書き込みモード(第2引数に `2`)」を指定してファイルを開いたその瞬間、元々あったファイルの中身は綺麗さっぱり消去され、0バイトの空のキャンバスになります。
そこからデータを書き込んでいくわけですが、もし書き込みの「最中」にスクリプトがエラー落ちしたり、OSがクラッシュしたりするとどうなるか。ファイルには「途中まで書きかけのゴミデータ」残されたままになります。元ファイルはすでに消えているため、データの復元は不可能。これがデータ破損のメカニズムです。
2. 解決策:アトミック書き換え(Atomic Replace)とは?
この問題をスマートに解決するのが、データベースの世界などでも常識として使われている「アトミック(不可分)操作」の考え方です。
アトミック書き換えのアルゴリズムは驚くほどシンプルです。
1. 直接本番ファイルを触らない。
2. 別の場所(または別名)に「一時ファイル(Temporary File)」を作成し、そこにすべてのデータを完全に書き切る。
3. 書き込みが100%成功したことを確認してから、一瞬の早業で「一時ファイルを本番ファイルにリネーム(または上書き移動)」する。
[本番ファイル (config.ini)] ──────────────┐
│ 安全!最後まで無事
[一時ファイル (config.tmp)] ──(全書き込み)──┘
↓ (一瞬で差し替え!)
[本番ファイル (config.ini)] ← 中身は最新!
これなら、書き込み途中にエラーが起きたとしても、影響を受けるのは「誰も見ていない一時ファイル」だけ。本番ファイルは、次の瞬間に完璧なデータで置き換えられるか、あるいは古い状態のまま完全に守られるかのどちらかになります。「中途半端な壊れ方」が物理的に起きなくなるのです。
—
3. 【実践】FSOによるアトミック書き換えの実装コード
それでは、現場でそのままコピペして使える堅牢なVBScriptのサンプルコードを見てみましょう。エラーハンドリング(`On Error Resume Next`)も組み合わせた、実務仕様のフルセットです。
Option Explicit
Sub SafeUpdateConfig()
Dim fso, targetPath, tempPath, ts
Dim folderPath, tempFileName
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ パスの定義
targetPath = “C:\Data\config.ini”
folderPath = fso.GetParentFolderName(targetPath)
‘ 一意な一時ファイル名を生成(他のプロセスと衝突しないようランダムなGUIDやユニーク名を利用)
‘ ここではシンプルに元のファイル名に .tmp を付与し、さらにランダム値を挟みます
Randomize
tempFileName = “config_” & Int((99999 – 10000 + 1) Rnd + 10000) & “.tmp”
tempPath = fso.BuildPath(folderPath, tempFileName)
On Error Resume Next
‘ ステップ1: 安全な「一時ファイル」に対して書き込みを行う
‘ (ここでエラーが起きても、本番ファイルは一切傷つかない)
Set ts = fso.CreateTextFile(tempPath, True)
If Err.Number <> 0 Then
WScript.Echo “エラー: 一時ファイルの作成に失敗しました。 (” & Err.Description & “)”
Exit Sub
End If
‘ データを書き込む(実際の業務データをここに記述)
ts.WriteLine “[Settings]”
ts.WriteLine “LastUpdate=” & Now
ts.WriteLine “Status=Ready”
ts.Close
If Err.Number <> 0 Then
WScript.Echo “エラー: 書き込み中に障害が発生しました。”
‘ 念のため一時ファイルが残っていれば削除
If fso.FileExists(tempPath) Then fso.DeleteFile tempPath, True
Exit Sub
End If
‘ ステップ2: 書き込み完了後、本番ファイルをアトミック(瞬時)に置き換える
‘ FSOの CopyFile または MoveFile を上書きモード(True)で実行
fso.MoveFile tempPath, targetPath
If Err.Number <> 0 Then
WScript.Echo “致命的エラー: ファイルの置換に失敗しました。 (” & Err.Description & “)”
‘ クリーンアップ
If fso.FileExists(tempPath) Then fso.DeleteFile tempPath, True
Exit Sub
End If
On Error GoTo 0
WScript.Echo “ファイルの安全な更新が完了しました!”
Set ts = Nothing
Set fso = Nothing
End Sub
‘ 関数の実行
SafeUpdateConfig()
コードの重要ポイント解説
1. 一意な一時ファイル名の生成
`Randomize` と `Rnd` を使って、毎回異なるファイル名(例: `config_83921.tmp`)を生成しています。もし同じフォルダ内で複数のスクリプトが同時に走った場合でも、一時ファイル同士が衝突してデータを上書きし合わないための知恵です。
2. `MoveFile` によるアトミックな置換
FSOの `MoveFile` メソッドは、同一ボリューム(同じドライブ内)であれば、OSレベルで「名前の変更(リネーム)」として処理されます。これが一瞬で完了する(アトミックである)理由です。
3. 二重の安全網(クリーンアップ)
万が一、置換の直前で予期せぬエラーが起きた場合でも、ゴーストのようにゴミの一時ファイルがディスクを圧迫し続けないよう、エラー処理内で `fso.DeleteFile` による掃除を行っています。
—
4. 陥りやすい罠・注意点
このアトミック書き換えパターンを実装する上で、プログラマーがハマりがちな「落とし穴」が2つあります。ここを抑えておけば完璧です。
罠①:別ドライブへ `MoveFile` しようとしてエラーになる
FSOの `MoveFile` で異なるドライブ間(例えば `C:` から `D:` へ)ファイルを移動しようとすると、OSは「移動」ではなく「コピー&旧ファイルの削除」という非アトミックな挙動をとります。さらに、ディスク容量不足などで失敗するリスクもあります。
鉄則: 一時ファイルは、必ず「本番ファイルと全く同じフォルダ内(同一ボリューム内)」に作成してください。
罠②:ファイル共有違反(Permission Denied)
他のアプリケーション(Excelや別の常駐監視プログラムなど)が本番ファイルや一時ファイルをガッチリ掴んで離さない場合、`MoveFile` の瞬間にはじかれてエラーになります。
重要ファイルを扱うバッチ処理では、ファイル入出力の前後で他プロセスとの競合が起きないような運用設計(排他制御)を意識することが大切です。
—
まとめ
いかがでしたでしょうか?
今回は、FSOを使ったファイル操作における最高峰の安全策「アトミック書き換えパターン」について解説しました。
- 直接ファイルを上書きするな。まずは安全な別名の一時ファイルに書き切れ。
- 書き込みが終わったら、OSのファイル移動機能で一瞬で差し替えろ。
この2つの原則を守るだけで、あなたの書くVBScriptの信頼性はプロのインフラ水準へと跳ね上がります。「動けばいいや」のコードから卒業し、障害にびくともしない堅牢な自動化スクリプトを構築していきましょう。
ここをクリアしたあなたなら、もうVBScriptのファイル操作で恐れるものはありません。明日からの開発現場で、ぜひこのテクニックを役立ててくださいね!
