【テクニカル・上級編】【中級者向け】ネットワークドライブ切断を検知して安全にプロジェクトを保存するリトライ処理 – Project VBA解析バイブル

スポンサーリンク

ネットワーク越しの保存は「水物」である ― Project VBAにおける堅牢なリトライ戦略

Project VBA(Microsoft ProjectのVBA)を扱うエンジニアにとって、ネットワークドライブ上のプロジェクトファイル保存は常に「悪夢」と隣り合わせだ。VPNの瞬断、ファイルサーバーのロック、あるいはWindowsのファイルシステムキャッシュの気まぐれ。

標準的な `FileSave` メソッドを信じて疑わない者は、いつか必ず「保存失敗によるデータロスト」という致命的な代償を支払うことになる。

今日は、単なるエラーハンドリングの枠を超え、Windows APIを駆使して「接続状態を物理的に検知」し、再試行を行う極限のセーフティネットの実装論を共有する。

1. なぜ、標準の保存ルーチンでは不十分なのか

VBAの `Application.FileSave` は非常に脆弱だ。ネットワークが切断された際、APIはタイムアウトまで待機し、そのまま無慈悲にランタイムエラーを投げる。

ここで重要なのは、「エラーが起きた」という事実だけでなく、「何が原因で失敗したのか」を低レイヤーで特定することだ。単なる `On Error Resume Next` で誤魔化すのは素人の所業。我々がやるべきは、接続の死活監視と、オブジェクト解放によるメモリのクリーンアップを伴う、戦略的なリトライである。

2. 実装の核心:WNetGetConnectionによるネットワーク監視

ネットワークドライブの生死を確認するためには、`mpr.dll` の `WNetGetConnection` を利用する。これはOSレベルでネットワークパスの生存を確認する最も低コストな手法だ。

以下のコードは、保存失敗時に指定回数リトライを試み、その過程でネットワークの導通確認を挟む堅牢なルーチンである。

Option Explicit

‘ ネットワーク接続確認のためのWin32 API宣言
Private Declare PtrSafe Function WNetGetConnection Lib “mpr.dll” Alias “WNetGetConnectionA” ( _
ByVal lpszLocalName As String, _
ByVal lpszRemoteName As String, _
ByRef cbRemoteName As Long) As Long

”’

”’ ネットワークドライブの生存確認
”’

Private Function IsNetworkPathAlive(ByVal Path As String) As Boolean
Dim driveLetter As String
Dim buffer As String 255
Dim bufferLen As Long

driveLetter = Left(Path, 2)
bufferLen = 255

‘ 0が返れば接続成功、それ以外は切断または非ネットワークパス
IsNetworkPathAlive = (WNetGetConnection(driveLetter, buffer, bufferLen) = 0)
End Function

”’

”’ 堅牢なプロジェクト保存ルーチン
”’

Public Sub RobustSaveProject(ByVal filePath As String)
Dim retryCount As Integer
Dim maxRetries As Integer: maxRetries = 3
Dim success As Boolean: success = False

Do While retryCount < maxRetries And Not success On Error Resume Next ' 明示的にファイルを保存 Application.FileSaveAs Name:=filePath If Err.Number = 0 Then success = True Else retryCount = retryCount + 1 ' ここでネットワークの死活を確認 If Not IsNetworkPathAlive(filePath) Then Debug.Print "ネットワーク切断を検知。再接続待機中... (" & retryCount & "/" & maxRetries & ")" Sleep 2000 ' 2秒待機(Sleep関数は別途定義が必要) Else ' ネットワークは生きているが保存に失敗した場合は、少し時間を置いてメモリを解放する DoEvents Sleep 1000 End If End If On Error GoTo 0 Loop If Not success Then MsgBox "致命的エラー: 保存に失敗しました。ローカルへの退避を推奨します。", vbCritical End If End Sub ---

3. メモリとリソースの最適化:エンジニアの作法

上記のコードに加え、大規模なプロジェクトを扱う際は以下の点に留意せよ。

1. DoEventsの適切な挿入: ネットワークI/Oを待機する間、VBAのシングルスレッドモデルをブロックしないこと。`DoEvents` を挟むことで、OSがネットワークリソースを再確保する隙間を作る。
2. オブジェクトの明示的解放: プロジェクト操作後に `Set Project = Nothing` を行うことは基本だが、特にファイルシステムオブジェクト(FSO)を併用する場合は、スコープを最小限にし、即座にメモリを解放せよ。VBAのガベージコレクションは信用するな。
3. レガシー環境への配慮: `PtrSafe` キーワードを必ず付与し、64bit/32bit双方のOffice環境で動作するように設計する。これがプロフェッショナルとしての最低限の要件だ。

結論:技術は「念のための備え」に宿る

システムは必ず壊れる。ネットワークは必ず切れる。
「うまく動いているとき」のコードは誰にでも書けるが、「システムが悲鳴を上げているときに、いかに優雅にリカバリするか」こそが、シニアエンジニアの価値を決める。

今回提示したリトライロジックは、単なるコードの断片ではない。貴殿が抱えるレガシーシステムを、明日からの運用から解放するための「盾」である。このアーキテクチャを理解し、現場の過酷な環境へと実装してほしい。

健闘を祈る。

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