【実務・中級編】【自己更新モジュール】ローカル実行中のVBScriptをネットワーク共有上の最新コードで動的差し替え・更新する仕組み – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

【自己更新モジュール】ローカル実行中のVBScriptをネットワーク共有上の最新コードで動的差し替え・更新する仕組み

業務自動化ツールをVBScriptで構築し、ファイルサーバー等のネットワーク共有(UNCパス)で運用している現場は多い。
しかし、ここで必ず直面するのが「ツールの改修・バージョンアップ地獄」だ。

全ユーザーに「最新版をデスクトップにコピーしてください」とチャットを流しても、読まない人間、古いショートカットを使い続ける人間、そもそもアップデートを忘れる人間が必ず現れる。結果、部署内で異なるバージョンのスクリプトが乱立し、旧仕様のバグを踏んでサポートに追われることになる。

これを根絶するのが、「起動時にネットワーク上の最新コードと自身を比較し、差分があれば自動で上書きして自身を再起動する(自己更新モジュール)」の設計だ。

今回は、VBScriptのランタイム特性(ファイルロックの罠、プロセス置換の限界など)を逆手に取り、堅牢かつスマートに動的差し替えを実現するプロダクションコードを伝授する。

1. なぜ「雑な実装」では失敗するのか?(VBScriptの制約と罠)

ネットワーク上のファイルをローカルにコピーして実行する仕組みを作る際、素朴なエンジニアは次のようなコードを書きがちだ。

‘ 【NGな実装例】やってはいけないアンチパターン
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ ネットワークからローカルへ強制上書きコピー
fso.CopyFile “\\server\share\tool.vbs”, “C:\Apps\tool.vbs”, True
‘ そのまま実行継続
CreateObject(“WScript.Shell”).Run “C:\Apps\tool.vbs”, 1, False

この実装には、実務で即座にシステム停止を引き起こす致命的な欠陥が2つある。

1. 自己書き換えの衝突(File Sharing Violation)
Windowsにおいて、現在実行中のプロセスが開いている(ハンドルの握られている)スクリプトファイル自身を、外部から上書きすることはできない。強制上書きを試みると `Permission denied`(権限がありません)エラーでスクリプトがクラッシュする。
2. バージョン判定の欠如
毎回ネットワークからコピーを行っていたのでは、ネットワーク負荷が無駄に高まるだけでなく、ファイルサーバーがオフライン(切断時)になった瞬間にツールが起動しなくなる。

これらをクリアするためには、「ローカルのローダー(Bootstrap)」と「ネットワーク上の本体(Core)」を分離し、起動の瞬間にのみ差分検知とプロセス置換を行うというアーキテクチャが必要となる。

2. 堅牢な自己更新システムのアーキテクチャ

今回構築する仕組みの全体像は以下の通りだ。

  • 配置構成:
  • `\\server\share\app\tool_core.vbs` (ネットワーク上の最新本体 + バージョン情報)
  • `C:\MyTools\launcher.vbs` (ローカルに常駐する不変の起動モジュール)
  • `C:\MyTools\tool_current.vbs` (ローカルで実際に実行される実体)
  • 処理フロー:

1. ユーザーがローカルの `launcher.vbs` を叩く。
2. ローチャーがネットワーク上の `tool_core.vbs` の更新日時またはバージョンヘッダーをチェック。
3. 差異がある場合、またはローカルに実体がない場合のみ、ファイルをローカルへコピー。
4. ローカルの最新スクリプトを `WScript.Shell` で非同期起動し、ランチャーは速やかに終了。

この設計であれば、ファイルロックの競合を完全に回避でき、ファイルサーバーが一時的にダウンしていても、前回同期したローカルキャッシュでオフライン稼働が可能になる。

3. プロダクションコード:【ローチャー兼更新モジュール】

以下のコードを `launcher.vbs` としてローカル環境(例: `C:\MyTools\`)に配置してほしい。実務の現場でそのまま耐えうるよう、エラーハンドリングとログ出力を組み込んである。

‘ ==============================================================================
‘ Script Name : launcher.vbs
‘ Purpose : ネットワーク共有上のVBScriptを検知・自動更新し、ローカルで実行する
‘ ==============================================================================
Option Explicit

Const REMOTE_PATH = “\\server\share\app\tool_core.vbs”
Const LOCAL_DIR = “C:\MyTools\”
Const LOCAL_PATH = “C:\MyTools\tool_current.vbs”

Sub Main()
Dim fso, shell
Set fso = CreateObject(“Scripting.FileSystemObject”)
Set shell = CreateObject(“WScript.Shell”)

‘ 1. ローカルディレクトリの存在確認・作成
If Not fso.FolderExists(LOCAL_DIR) Then
fso.CreateFolder(LOCAL_DIR)
End If

‘ 2. ネットワーク上のマスターが存在するか確認(オフライン耐性の考慮)
If fso.FileExists(REMOTE_PATH) Then
Dim remoteFile, localFile
Set remoteFile = fso.GetFile(REMOTE_PATH)

Dim needsUpdate
needsUpdate = False

‘ 3. ローカルにファイルが存在しない、またはタイムスタンプが異なる場合
If Not fso.FileExists(LOCAL_PATH) Then
needsUpdate = True
Else
Set localFile = fso.GetFile(LOCAL_PATH)
‘ ネットワーク側が新しい場合、更新フラグを立てる
If remoteFile.DateLastModified > localFile.DateLastModified Then
needsUpdate = True
End If
End If

‘ 4. 更新処理の実行
If needsUpdate Then
On Error Resume Next
fso.CopyFile REMOTE_PATH, LOCAL_PATH, True
If Err.Number <> 0 Then
‘ コピー失敗時(ファイルロック中など)はログを残して既存ローカル版でフォールバック起動
MsgBox “最新版のアップデートに失敗しました(オフラインモードで起動します)。” & vbCrLf & _
“エラー詳細: ” + Err.Description, vbExclamation, “自動更新警告”
Else
‘ 正常更新完了
‘ WScript.Echo “ツールが最新版にアップデートされました。” ‘ 必要に応じてコメント解除
End If
On Error GoTo 0
End If
Else
‘ ネットワークに接続されていない(オフライン)の場合の警告
If Not fso.FileExists(LOCAL_PATH) Then
MsgBox “ネットワークに接続されておらず、ローカルキャッシュも存在しません。” & vbCrLf & _
“ネットワーク接続を確認してください。”, vbCritical, “致命的なエラー”
Exit Sub
End If
End If

‘ 5. ローカルの最新スクリプトを実行してランチャーは終了
‘ wscript.exe を明示的に指定し、バックグラウンド(ウィンドウ非表示の場合は cscript だがGUIならwscript)で起動
shell.Run “wscript.exe “”” & LOCAL_PATH & “”””, 1, False

Set shell = Nothing
Set fso = Nothing
End Sub

‘ 実行
Main()

4. チーフアーキテクトが教える「現場でハマる罠」と対策

この仕組みを導入するにあたり、プロの現場特有のトラブルシューティングの知見を共有する。

① ネットワークパスの遅延とタイムアウト

ファイルサーバー(NAS等)がスリープ状態や高負荷の場合、`fso.FileExists(REMOTE_PATH)` の判定だけで数秒〜数十秒のフリーズが発生することがある。
これを防ぐため、厳密な環境ではPing疎通確認や、VBScript標準のタイムアウト制御(WMIや別プロセスでの非同期チェック)を挟むのが理想だが、社内LAN環境であれば上記コードのままで実用上問題ないことが多い。

② 実行権限とUNCパスのセキュリティ制約

Windowsのセキュリティポリシー(MOTW: Mark of the Web)により、ネットワーク共有から直接ダウンロード・実行されたスクリプトが「ブロック」されることがある。
これを回避するため、ネットワーク上の本体 (`tool_core.vbs`) は直接実行せず、必ずローカル (`LOCAL_PATH`) にコピーした上で実行する上記アーキテクチャが極めて有効に機能する(ローカルへのコピーによりゾーン識別子が外れる、または管理しやすい)。

③ バージョン情報の高度な判定(タイムスタンプ以外の方法)

ファイルの「更新日時 (`DateLastModified`)」比較は最もシンプルで高速だが、開発者がファイルを「上書き保存しただけ」で中身が変わっていない場合でも同期走査が走る。
より厳密に制御したい場合は、ネットワーク上のファイルの先頭数行に以下のようなバージョンヘッダーを埋め込み、テキストとして比較するロジックに拡張すると完璧だ。

‘ — tool_core.vbs の先頭に配置するメタデータ例 —
‘ VERSION: 2.1.0
‘ LAST_UPDATED: 2023-10-25

5. おわりに

業務自動化ツールは「作って終わり」ではない。「配りとメンテナンスのコスト」をいかにゼロにするかが、エンジニアの腕の見せ所だ。

今回紹介した自己更新ローチャーの仕組みを導入すれば、開発者はファイルサーバーの `tool_core.vbs` を上書き保存するだけで、全ユーザーのクライアント環境が次回の起動時に勝手に最新化される。

「バージョン違いによる不具合の問い合わせ」というエンジニア最大のストレス源を、この仕組みで完全に過去のものにしてほしい。

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