【入門編】【マルチバリューレジストリ編集】WMI StdRegProv を使用した REG_MULTI_SZ(複数文字列値)の安全なパースと動的更新 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

こんにちは!VBScriptの世界へようこそ。
マクロの記録ボタンを押すだけの世界から一歩踏み出し、WindowsのOS内部を自在に操るスクリプトの世界へようこそ。ここをクリアすれば、あなたも立派なWindows自動化エンジニアの仲間入りです。温かく、そして深く、一緒に技術の本質を紐解いていきましょう。

さて、今回のテーマは「マルチバリューレジストリ編集」です。
レジストリには様々なデータ型がありますが、中でも`REG_MULTI_SZ`(複数文字列値)という、「ひとつのキーの中に、複数のテキストを改行区切りでリストのように格納できる形式」に苦しめられたことはありませんか?

VBScriptでこれを扱おうとすると、通常の文字列と同じようにはいかず、予期せぬエラーが出たり、既存のリストを丸ごと上書きして消してしまったりと、なかなかの曲者です。

今回は、WMI(Windows Management Instrumentation)の提供する至高のレジストリ操作クラス `StdRegProv` を駆使し、「既存のリストを破壊せず、安全に要素を追加・削除・更新する」ための極限のテクニックを伝授します。

なぜ `REG_MULTI_SZ` はVBScriptで嫌われるのか?

レジストリの標準的な操作オブジェクトである `WScript.Shell` の `RegRead` / `RegWrite` メソッドは、非常にシンプルで使いやすい反面、`REG_MULTI_SZ` を読み込むと、VBScriptが理解しやすい「配列」ではなく、特殊なVariant型(あるいは単一の文字列)として返してきたり、書き込み時に型が一致せずに弾かれたりします。

ここで登場するのが、WMIの `StdRegProv` です。
これを使うと、OSの奥深くにあるレジストリを、VBScriptから「配列(Array)」として直接安全に読み書きできるようになります。

StdRegProv の基本構造

WMIの `StdRegProv` は、ローカルコンピュータの `root\default` 名前空間に存在します。呼び出すときは、少しお作法が必要です。

‘ WMIオブジェクトとStdRegProvの取得(お決まりの召喚呪文)
Dim oReg, sComputer
sComputer = “.”
Set oReg = GetObject(“winmgmts:\\” & sComputer & “\root\default:StdRegProv”)

この `oReg` さえ手に入れば、あとはメソッドを呼び出すだけで、レジストリの配列データを完璧にコントロールできるようになります。

【実践】安全に配列をパース・更新する全コード

それでは早速、開発現場でそのままコピペして使える実践的なコードを見ていきましょう。
今回は例として、環境変数やシステム設定によく使われる `REG_MULTI_SZ` 型のデータを対象に、「指定した値がなければ追加し、あれば何もしない(あるいは削除する)」という安全な動的更新を行います。

以下のコードをメモ帳に貼り付け、拡張子を `.vbs` にして保存して実行してみてください(※操作するレジストリパスはテスト用の安全な場所に書き換えてくださいね)。

Option Explicit

‘ =========================================================================
‘ スクリプト名: UpdateMultiStringRegistry.vbs
‘ 概要: WMI StdRegProv を使用した REG_MULTI_SZ の安全なパースと動的更新
=========================================================================

Dim sHives, sKeyPath, sValueName, sTargetValue
Dim oReg, lRet, arrValues, i, bFound, newArr()

‘ 1. レジストリのターゲット設定 (HKEY_CURRENT_USER のテスト用パス)
sHives = &H80000001 ‘ HKEY_CURRENT_USER の定数
sKeyPath = “Software\MyTestApp”
sValueName = “AllowedServers”
sTargetValue = “server-backup-01.local” ‘ 追加・確認したい値

‘ 2. WMI StdRegProv オブジェクトの接続
Set oReg = GetObject(“winmgmts:\\.\root\default:StdRegProv”)

‘ 3. 既存の REG_MULTI_SZ データを配列として取得
‘ GetMultiStringValue メソッドは、データをVariant配列として取得します
lRet = oReg.GetMultiStringValue(sHives, sKeyPath, sValueName, arrValues)

‘ エラーハンドリング(キーや値が存在しない場合の初動対応)
If lRet <> 0 Then
WScript.Echo “対象のキーまたは値が存在しません。新規に作成します。”
‘ 存在しない場合は、ターゲット値だけが入った初期配列を作成
ReDim arrValues(0)
arrValues(0) = sTargetValue
Else
‘ 4. 既存データのパース(重複チェックと存在確認)
bFound = False
For i = LBound(arrValues) To UBound(arrValues)
If LCase(arrValues(i)) = LCase(sTargetValue) Then
bFound = True
Exit For
End If
Next

If bFound Then
WScript.Echo “指定された値 ‘” & sTargetValue & “‘ は既に存在します。更新をスキップします。”
WScript.Quit
Else
‘ 5. 既存の配列を拡張し、新しい要素を追加する(動的更新)
‘ UBound(arrValues) + 1 でサイズを1つ増やし、Preserveで既存データを保持
ReDim Preserve arrValues(UBound(arrValues) + 1)
arrValues(UBound(arrValues)) = sTargetValue
WScript.Echo “既存のリストに新しい値を追加します。”
End If
End If

‘ 6. レジストリへ書き戻す (SetMultiStringValue)
lRet = oReg.SetMultiStringValue(sHives, sKeyPath, sValueName, arrValues)

If lRet = 0 Then
WScript.Echo “REG_MULTI_SZ の更新が正常に完了しました!”
Else
WScript.Echo “エラー: レジストリの書き込みに失敗しました。エラーコード: ” & lRet
End If

‘ クリーンアップ
Set oReg = Nothing

コードの核心:ここがプロの技術

上記のコードで、VBScript中級者へのステップアップとなる重要なポイントを3つ解説します。

1. レジストリハイブの「定数」を理解する

WMIを叩く際、`HKEY_CURRENT_USER` や `HKEY_LOCAL_MACHINE` は文字列ではなく、16進数の数値(定数)で指定する必要があります。

  • `HKEY_CLASSES_ROOT` = `&H80000000`
  • `HKEY_CURRENT_USER` = `&H80000001`
  • `HKEY_LOCAL_MACHINE` = `&H80000002`

このお約束を覚えておくだけで、WMIを使ったレジストリ操作の幅が一気に広がります。

2. `GetMultiStringValue` と `SetMultiStringValue` の挙動

通常の `WScript.Shell` では文字列の配列をうまく扱えない場面でも、`StdRegProv` のこれら専用メソッドを使えば、VBScriptの「配列(Array)」とレジストリの `REG_MULTI_SZ` が自動的に相互変換されます。これが、安全なパースを行える最大の理由です。

3. `ReDim Preserve` による安全な拡張

VBScriptで配列の要素数を動的に増やすときは、`ReDim Preserve` を使います。

ReDim Preserve arrValues(UBound(arrValues) + 1)
arrValues(UBound(arrValues)) = sTargetValue

`Preserve` を忘れると、これまで存在していた大切な既存のリストがすべて消去されてしまうという大惨事(データ損失)につながります。マルチバリュー編集において、このキーワードは命綱です。必ずセットで覚えておきましょう。

陥りがちなエラーと対策

1. エラーコード `2` (ファイルが見つかりません、等の意)が出る

  • 原因: 指定したレジストリアイクス(`sKeyPath`)自体が存在しない場合に発生します。
  • 対策: サンプルコードのように、`lRet <> 0` の場合は「新規作成モード」として配列を初期化するロジックを必ず組み込んでください。

2. 大文字・小文字の不一致による二重登録

  • 原因: レジストリ値はシステムによって大文字・小文字が混在することがあります。
  • 対策: パース時の比較には `LCase()` や `UCase()` を用いて、大文字小文字を区別しない(ケースインセンシティブな)比較を行うのがプロの作法です。

おわりに

いかがでしたでしょうか?
一見難しそうに見える `REG_MULTI_SZ` の操作も、WMIの `StdRegProv` と配列の動的制御(`ReDim Preserve`)を組み合わせれば、怖くありません。

ここをクリアできたあなたなら、VBScriptの基本はもうバッチリです!現場の自動化スクリプトに、ぜひこの知見を取り入れてみてください。あなたのエンジニアライフが、より快適でスマートなものになることを応援しています!

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