VBScriptを掌握する:MSXML2.XMLHTTPによる大容量ファイル・ストリーム転送の極意
VBScriptは「レガシー」と呼ばれ久しい。しかし、エンタープライズの現場でWindowsの標準機能のみで完結する自動化を求められたとき、これほど軽量かつ強力な武器はない。
多くのエンジニアが `ADODB.Stream` と `MSXML2.XMLHTTP` を組み合わせる際、メモリ不足(Out of Memory)や、ファイル破損という壁にぶつかる。今回は、数GB級のファイルをも安定してハンドリングするための、アーキテクトレベルの流儀を授ける。
—
1. メモリを殺すな:ADODB.Streamの絶対原則
大容量ファイルを扱う際、最もやってはいけないのが「バイナリデータを一度メモリ上に展開する」ことだ。`ResponseBody` をそのまま `Write` メソッドに投げれば、それはシステムメモリを食いつぶす爆弾となる。
我々が取るべき戦略は、「受信バッファの最適化」と「ストリームの排他制御」である。
実装の肝:ストリーム転送コード
‘ ダウンロード関数: 大容量ファイルを安全に書き出す
Sub DownloadFile(url, savePath)
Dim http, stream
Set http = CreateObject(“MSXML2.XMLHTTP”)
Set stream = CreateObject(“ADODB.Stream”)
‘ 1. 通信プロトコルの確立
http.Open “GET”, url, False
http.Send
‘ 2. 応答検証: Content-Lengthが取れない場合は異常とみなす
Dim contentLength
contentLength = http.getResponseHeader(“Content-Length”)
‘ 3. ストリーム初期化
stream.Type = 1 ‘ adTypeBinary
stream.Open
‘ 4. バッファ書き出し: ここで直接メモリを流し込む
‘ 警告: ファイルサイズが数GBを超える場合、一度のSendではメモリ溢れを起こす可能性がある
‘ 厳密にはRangeヘッダーを用いた分割取得が推奨されるが、まずは基本を徹底する
stream.Write http.responseBody
‘ 5. 書き込みと整合性チェック
stream.SaveToFile savePath, 2 ‘ adSaveCreateOverWrite
‘ 6. 徹底的なオブジェクト解放(重要)
stream.Close
Set stream = Nothing
Set http = Nothing
End Sub
—
2. なぜそのコードは「破損」するのか
現場でよくある質問が「ダウンロードしたはずのファイルが壊れている」というものだ。原因は9割が以下のいずれかである。
- Content-Lengthの不一致: 通信が途中で切断されても、`XMLHTTP` はエラーを吐かずに終了することがある。`http.Status` が 200 であることを確認するだけでなく、`stream.Size` と `Content-Length` を比較するロジックを必ず挟め。
- バイナリモードの誤解: `ADODB.Stream` の `Type` を指定し忘れると、既定のテキストモードで解釈され、バイナリデータが文字コード変換(Shift-JISへの誤変換など)によって破壊される。必ず `1 (adTypeBinary)` を指定せよ。
—
3. シニアエンジニアの嗜み:メモリ管理の美学
VBScriptには自動ガベージコレクションがあるが、それは「いつか」解放されるという希望的観測に過ぎない。特にWSH(cscript.exe)で長時間稼働するバッチ処理において、オブジェクトの解放を怠ることは自殺行為だ。
「明示的解放」の作法
`Set obj = Nothing` を書くことは、単なる儀式ではない。COMコンポーネントの参照カウントを確実にゼロにし、メモリリークを未然に防ぐための防御的プログラミングである。
‘ エラーハンドリングを含めた堅牢なパターン
On Error Resume Next
‘ …処理…
If Err.Number <> 0 Then
WScript.Echo “Error: ” & Err.Description
End If
‘ 終了処理は常に実行されるようにする
On Error Goto 0
Set obj = Nothing
—
4. アーキテクトからの提言:限界を見極める
VBScriptによる `MSXML2.XMLHTTP` は、あくまで「同期通信」だ。ファイルサイズが数GBを超え、通信品質が安定しない環境では、VBScript単体で挑むのは限界がある。
もし、貴方の現場が以下のような環境であれば、迷わず次のステップへ移行すべきだ。
1. タイムアウトの頻発: `WinHttp.WinHttpRequest.5.1` へ切り替えろ。`SetTimeouts` メソッドにより、より細かい通信制御が可能だ。
2. 進捗表示が必要: 非同期イベントハンドラを利用するか、PowerShellの `System.Net.WebClient` を経由して呼び出すラッパーを用意せよ。
VBScriptは、シンプルであるがゆえに書き手の技量が露骨に出る。オブジェクトのライフサイクルをコントロールし、リソースの枯渇を許さない。それこそが、伝説的なコードの条件だ。
—
まとめ:
- `ADODB.Stream` はバイナリモードで運用せよ。
- `Content-Length` を信じるな、書き込み後の `Size` を確認せよ。
- オブジェクトは `Nothing` で殺せ。
この作法を守れば、VBScriptは今なお、エンタープライズの最前線で最高の効率を叩き出すだろう。健闘を祈る。
