VBScriptで構築する「堅牢なログアーカイブ戦略」:MakeCABとの連携でファイルシステムを掌握せよ
業務自動化の現場において、ファイルシステムの整理は「塵も積もれば山となる」典型的な課題だ。特に、野放図に増殖するログファイルはディスクを圧迫し、監視ツールやバックアップのボトルネックとなる。
多くの初学者はここで `FSO (FileSystemObject)` の `.Delete` を安易に呼び出し、またある者は不完全な同期処理でファイルをロックし、業務を停止させる。我々エンジニアが目指すべきは、「条件抽出・整合性チェック・非同期圧縮・安全な破棄」という一連のトランザクションを、堅牢かつクリーンに完結させることだ。
本稿では、Windows標準の `MakeCAB` を活用し、VBScriptでログファイルをスマートに圧縮・退避させるプロフェッショナルな設計術を伝授する。
—
1. なぜ「非同期実行」が必須なのか
VBScriptの `WScript.Shell.Run` を使う際、第二引数 `bWaitOnReturn` を安易に `True` にしてはいけない。圧縮対象が数ギガバイトに及ぶ場合、スクリプトが「圧縮待ち」でハングアップし、OSの応答性能を著しく低下させるからだ。
また、`MakeCAB` は優秀だが、実行環境のパスや権限管理を怠ると即座に沈黙する。我々は「実行したかどうか」をログに残し、ファイルシステムへの書き込み権限を事前に検証するアーキテクチャを採用する。
—
2. 実務直結のプロダクションコード
このコードは、指定フォルダ内の「30日以上前のログ」を抽出し、圧縮後に元ファイルを消去するテンプレートだ。保守性を考慮し、設定値とロジックを分離している。
Option Explicit
‘ — 設定エリア —
Const TARGET_DIR = “C:\Logs\App”
Const ARCHIVE_DIR = “C:\Archives”
Const RETENTION_DAYS = 30
‘ ——————
Dim fso, shell, folder, file, targetDate
Set fso = CreateObject(“Scripting.FileSystemObject”)
Set shell = CreateObject(“WScript.Shell”)
targetDate = DateAdd(“d”, -RETENTION_DAYS, Date)
‘ フォルダの存在確認(例外処理の基本)
If Not fso.FolderExists(TARGET_DIR) Then WScript.Quit
Set folder = fso.GetFolder(TARGET_DIR)
For Each file In folder.Files
‘ 拡張子が.logであり、かつ指定日数経過しているか
If LCase(fso.GetExtensionName(file.Name)) = “log” And file.DateLastModified < targetDate Then
Dim cabName, cabPath
cabName = file.Name & ".cab"
cabPath = ARCHIVE_DIR & "\" & cabName
' 圧縮コマンドの生成 (MakeCAB /V3 /D CompressionType=MSZIP)
' /V3: 詳細出力, MSZIP: 標準的な圧縮アルゴリズム
Dim cmd
cmd = "makecab """ & file.Path & """ """ & cabPath & """ > nul”
‘ 非同期で実行 (第2引数をFalseにすることでスクリプトを停止させない)
‘ ただし、大規模ファイルの場合は完了待ちが必要なケースもあるため、
‘ 厳密な整合性が求められる場合はループで完了チェックを行うのが定石
shell.Run cmd, 0, True
‘ 圧縮ファイルの生成を確認してから元ファイルを削除
If fso.FileExists(cabPath) Then
file.Delete True
WScript.Echo “Archived: ” & file.Name
End If
End If
Next
Set fso = Nothing
Set shell = Nothing
—
3. 開発リーダーからの「極限の知見」:3つの鉄則
現場でトラブルを起こさないために、以下の知見を脳に刻んでほしい。
① 拡張子ベースのフィルタリングを過信するな
`fso.GetExtensionName` での判定はあくまで補助だ。もしファイル名にドットが含まれる場合や、誤った命名規則のファイルが存在する場合、予期せぬ動作を招く。可能であれば、正規表現(`VBScript.RegExp`)を用いてファイル名のパターンを厳密にマッチングさせるべきだ。
② ディスクフル(容量不足)への防衛線
`MakeCAB` は一時的に元ファイルと同等以上の空き容量を要求することがある。圧縮処理前に `fso.GetDrive(fso.GetDriveName(ARCHIVE_DIR)).FreeSpace` を確認し、十分な空きがあるか判定するロジックを組み込むのが、真に「壊れないシステム」の条件だ。
③ ログの「二重削除」を防ぐ
ネットワークドライブを対象とする場合、I/Oの遅延で「ファイルがまだ存在している」と誤認することがある。`file.Delete` を呼び出す前に、`If fso.FileExists(cabPath) And fso.GetFile(cabPath).Size > 100 Then` のように、圧縮ファイルが空ではないことを確認する「ヘルスチェック」を必ず挟め。
—
最後に:なぜVBScriptを使うのか
「なぜ今さらVBScriptなのか」と問われれば、「環境を選ばず、即座にOSの深部にアクセスできるからだ」と答える。
PowerShellの方が高機能なのは自明だが、レガシーなWindows Server環境や、厳格なセキュリティポリシーで外部モジュールを一切許可されない現場において、VBScriptは依然として最強の武器である。
このスクリプトを基盤とし、君の環境に合わせて改良を加えてほしい。自動化とは、一度書いたコードが何千回もの「面倒な作業」を肩代わりしてくれる、エンジニアにとって最も報われる投資なのだから。
