【テクニカル・上級編】【上級プロフェッショナル向け】ネットワーク切断時のRPCサーバー不可エラー(0x800706BA)に対するFSO再接続&自動自己復旧 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

【上級プロフェッショナル向け】ネットワーク切断時のRPCサーバー不可エラー(0x800706BA)に対するFSO再接続&自動自己復旧

レガシーシステムの深部、あるいは堅牢性が求められる基幹バッチ処理の現場において、VBScript(Visual Basic Scripting Edition)とFileSystemObject(FSO)のコンビネーションは、今なおインフラストラクチャの隙間を埋める不可欠な道具として稼働し続けている。

だが、対象がローカルディスクではなく、SMB(Server Message Block)で接続されたネットワーク共有フォルダ(UNCパス)である場合、話は劇的に変わる。
ネットワークの瞬断、VPNの再接続、あるいはNAS側のメンテナンスによるセッション喪失。これらに直面した瞬間、FSOのメソッドは容赦なく致命的なランタイムエラーを吐き出す。

その代表格が、エラー番号 `-2147023174`(16進数表現:`0x800706BA`)、すなわち「RPC サーバーを利用できません」という例外だ。

本稿では、この不可抗力的な通信断絶エラーに対し、VBScriptの限界領域でいかにして「自己復旧(セルフヒーリング)」メカニズムを実装するか、その極限の知見を解説する。

—

1. ネットワークファイル操作における「RPCサーバー不可エラー(0x800706BA)」の正体

FSO(`Scripting.FileSystemObject`)は、内部的にWindowsのCOMコンポーネントとして動作し、ファイルシステムへのアクセスはWin32 APIやリモートプロシージャコール(RPC)層に依存している。

ネットワーク越しにUNCパス(例: `\\fileserver\share\data.csv`)へアクセスしている最中に物理的・論理的な切断が発生すると、以下の現象が連鎖的に起きる。

1. セッションの無効化: OSのネットワークリダイレクターがサーバーとのコネクション喪失を検知。
2. RPC通信のタイムアウト: FSOからの要求に対する応答が途絶え、COM層がハングアップ状態を回避するためにエラーを返却。
3. オブジェクトのゾンビ化: 既存の `FileSystemObject` インスタンスは、断絶前の不正な接続状態(キャッシュや無効なハンドル)を内部保持したまま「腐敗」する。

ここで最も重要な知見は、「死んだFSOインスタンスをそのまま使い回してリトライしても、永遠にエラー(0x800706BA)は解消されない」という事実だ。復旧のためには、エラー捕捉だけでなく、COMオブジェクト自体の完全な破棄(メモリ解放)と再生成が不可欠となる。

—

2. 設計思想:堅牢な自己復旧ループ(Self-Healing Pattern)

真にエンタープライズな耐性を持つコードを書くためには、以下の3層防御を構築する必要がある。

  • 精密なエラーハンドリング: `On Error Resume Next` と `Err.Number` による厳密なトラップ。
  • COMオブジェクトのライフサイクル管理: エラー発生時は即座に `Set fso = Nothing` を実行し、OSのリソースを完全に解放。
  • バックオフアルゴリズム(指数待機): ネットワーク復旧の猶予を与えるため、リトライごとに待機時間を延長する。

—

3. 実装コード:FSO自動自己復旧ファイル書き込み・読み込みエンジン

以下のコードは、ネットワーク共有フォルダへの書き込み処理中に `0x800706BA` をはじめとする通信エラーが発生した場合でも、自律的にコネクションを再構築し、最大リトライ回数まで粘り強く処理を完遂する実用スクリプトである。

Option Explicit

‘ ==============================================================================
‘ 処理設定
‘ ==============================================================================
Const TargetFilePath = “\\nas-server01\shared_folder\logs\system_operation.log”
Const MaxRetries = 5 ‘ 最大リトライ回数
Const InitialDelayMs = 2000 ‘ 初回リトライ時の待機時間(ミリ秒)

‘ メイン処理の実行
Call WriteLogWithAutoRecovery(TargetFilePath, “System heartbeat: Normal operation.”)

‘ ==============================================================================
‘ [メイン関数] ネットワーク耐性付きファイル書き込みラッパー
‘ ==============================================================================
Sub WriteLogWithAutoRecovery(ByVal filePath, ByVal logMessage)
Dim fso, ts
Dim attempt
Dim isSuccess
Dim currentDelay

attempt = 0
isSuccess = False
currentDelay = InitialDelayMs

Do While attempt < MaxRetries And Not isSuccess attempt = attempt + 1 ' 1. COMオブジェクトのインスタンス化(毎ループ新しく生成する点がキモ) Set fso = CreateObject("Scripting.FileSystemObject") ' 2. エラー監視の有効化 On Error Resume Next ' ネットワークパスへのアクセス(ここで0x800706BA等が発生し得る) ' ディレクトリが存在しない場合の自動作成も兼ねる Dim parentDir parentDir = fso.GetParentFolderName(filePath) If Not fso.FolderExists(parentDir) Then ' 簡易的にフォルダを作成(必要に応じた権限・存在チェック) fso.CreateFolder(parentDir) End If ' テキストファイルのオープン(ForAppending: 8, Create: True) ' ネットワーク切断時はこの行で致命的エラーが発生する Set ts = fso.OpenTextFile(filePath, 8, True) If Err.Number = 0 Then ' 書き込み実行 ts.WriteLine "[" & Now & "] " & logMessage ts.Close isSuccess = True Else ' エラーコードのキャッチ(0x800706BA = &H800706BA 等) Dim errNum errNum = Err.Number ' VBScriptで符号付き32bit整数として扱われるエラー番号の処理 If errNum < 0 Then errNum = errNum + 4294967296# WScript.Echo "[WARN] ネットワークエラーを検知しました。エラーコード: " & Hex(errNum) & _ " (試行回数: " & attempt & "/" & MaxRetries & ")" ' 【極限知見】壊れたオブジェクトとストリームの完全解放 On Error Resume Next If Not ts Is Nothing Then ts.Close Set ts = Nothing Set fso = Nothing ' ★ここでメモリ空間からゾンビCOMを完全にパージする ' ネットワークの復旧を待つ(バックオフ待機) Call Sleep(currentDelay) ' 待機時間を倍増させる(指数バックオフ) currentDelay = currentDelay 2 End If On Error GoTo 0 Loop ' 最終結果の判定 If isSuccess Then WScript.Echo "[INFO] ファイル操作が正常に完了しました。" Else WScript.Echo "[FATAL] 最大リトライ回数を超過しました。処理を中断します。" ' 必要に応じてここで管理者へのメール通知やイベントログ書込を実装 End If ' クリーンアップ Set ts = Nothing Set fso = Nothing End Sub ' ============================================================================== ' [ヘルパー関数] WScript.Sleepのラッパー(環境依存の回避) ' ============================================================================== Sub Sleep(ByVal milliSeconds) ' WScriptオブジェクトが利用できない環境(WSCなど)への配慮も含め、 ' 標準的なWScript.Sleepをコール WScript.Sleep milliSeconds End Sub ---

4. チーフアーキテクトが指摘する「実装上の罠とベストプラクティス」

このコードを実運用に投入する際、シニアエンジニアとして知っておくべきハードウェア・OSレイヤーの制約がいくつか存在する。

① UNCパスの正引きキャッシュ問題

Windowsはパフォーマンス最適化のためにネットワークパスの存在有無をキャッシュする。ネットワークが復旧した直後であっても、OSのキャッシュが古い状態(「到達不能」の判定)を維持している場合がある。
そのため、リトライ間隔をあまりに短く(例: 100msなど)設定すると、ネットワークが回復しているにもかかわらずOSレイヤーで弾かれ続ける現象が発生する。最低でも 2秒〜5秒 の初期ディレイと指数バックオフが必須となる。

② COMオブジェクトのスコープとメモリリーク

VBScriptの変数は動的だが、COMオブジェクト(`CreateObject` で生成したもの)は明示的に `Set xxx = Nothing` を行わないと、スクリプトが終了するまでプロセス内に参照カウントが残り続ける。
特に今回のようなリトライループ内では、エラー発生のたびに古いFSOインスタンスを破棄し、ループの先頭で新規インスタンスを生成し直すことが、メモリリークを防ぎつつ「綺麗で新鮮なネットワークセッション」を取得する唯一にして最大の秘訣である。

③ 権限と資格情報の有効性 (セッションの再認証)

VPN切断からの復帰時、ネットワーク共有フォルダに対するKerberosチケットやNTLMセッションが無効化されている場合がある。
FSOがアクセスする前に、一度 `net use` コマンド等で明示的な再認証を挟む設計(あるいはOSの自動再接続に委ねるための適切なタイムアウト設計)をインフラ側と合わせて検討することが、真のシステム安定稼働への近道となる。

—

総括

レガシーな技術と揶揄されがちなVBScriptであっても、OSの挙動、COMのライフサイクル、そしてネットワークの物理的・論理的特性を深く理解していれば、現代の不安定なクラウド・仮想ネットワーク環境であっても十分に戦える「自己復旧型プログラム」へと昇華させることができる。

「エラーを恐れるな。エラーを飲み込み、自律的に蘇るコードを書け。」――それが、極限の自動化を極めたアーキテクトの哲学である。

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