WMIを駆使してインフラ管理を自動化する!VBScriptによるリモートPCプロセス・サービス監視の極意
インフラ管理者の皆さん、日々のルーチンワークに追われていませんか?CPU使用率のチェック、サービスの稼働状況確認、そして時には止まってしまったプロセスの強制終了…これらを全て手作業で行うのは、時間も労力もかかり、ヒューマンエラーのリスクもつきまといます。
しかし、ご安心ください。VBScriptとWMI (Windows Management Instrumentation) を組み合わせれば、これらの作業を劇的に自動化し、インフラ管理の効率を飛躍的に向上させることが可能です。本記事では、開発プロジェクトのリーダーとして、皆さんが現場でそのまま活用できる、堅牢かつ保守性の高いスクリプト構築の「極意」を伝授します。
なぜWMIなのか? – 現場で求められる「確実性」と「拡張性」
WMIは、Windows OSの管理情報を取得・操作するための標準的なインターフェースです。OSの様々な情報(プロセス、サービス、ハードウェア、ネットワークなど)にアクセスでき、リモート管理も容易に行えます。
「なぜPythonやPowerShellではなく、VBScriptなのか?」と疑問に思う方もいるでしょう。確かに、近年はPythonやPowerShellがインフラ管理の現場で主流となりつつあります。しかし、VBScriptには、長年にわたりWindows環境に標準搭載されており、既存のシステムやレガシーな環境との親和性が非常に高いという強みがあります。また、WMIオブジェクトモデルはVBScriptとの相性が抜群であり、比較的容易に実装できるという利点もあります。
もちろん、WMIはPowerShellでも利用可能ですが、VBScriptだからこそ実現できる「手軽さ」と「既存資産の活用」という観点から、本記事ではVBScriptに焦点を当てます。
WMIクエリ言語 (WQL) – 現場の「要求」を「コード」に落とし込む魔法
WMIを利用する上で、中心となるのがWMI Query Language (WQL) です。これはSQLに似た構文を持ち、WMIリポジトリから必要な情報を効率的に抽出するための強力なツールです。
例えば、CPU使用率を取得したい場合、以下のようなWQLクエリを使用します。
SELECT LoadPercentage FROM Win32_Processor
このクエリは、`Win32_Processor` クラスから `LoadPercentage` プロパティを取得することを意味します。
WMIオブジェクトのライフサイクル – パフォーマンスの「鍵」を握る
WMIオブジェクトを扱う上で、そのライフサイクルを理解することはパフォーマンス最適化の観点から非常に重要です。
- `GetObject`: WMIサービスへの接続を確立し、名前空間(例: `winmgmts:\\.\root\cimv2`)内のオブジェクトを取得します。この処理は、接続確立に若干のオーバーヘッドが発生します。
- `ExecQuery`: WQLクエリを実行し、結果セットを取得します。クエリの複雑さや対象となるデータ量によって、実行時間が変動します。
- `_NewEnum`: 取得した結果セットを列挙するためのインターフェースです。各要素にアクセスするたびに、裏側でWMIへの問い合わせが発生する場合があります。
【重要】
不要なWMIオブジェクトの生成や、繰り返し同じオブジェクトへのアクセスは、パフォーマンスの低下を招きます。 効率的なスクリプトを作成するためには、取得したオブジェクトを適切に解放し、必要な情報だけを一度に取得することが鉄則です。
現場で役立つ!VBScriptによるWMI活用スクリプト例
それでは、具体的なスクリプト例を見ていきましょう。これらのスクリプトは、そのままコピー&ペーストして利用できるだけでなく、保守性も考慮した設計になっています。
1. リモートPCのCPU/メモリ使用率を取得する
‘==============================================================================
‘ スクリプト名: GetSystemInfo.vbs
‘ 説明: リモートPCのCPUおよびメモリ使用率を取得する
‘ 作成者: あなたの名前
‘ 作成日: YYYY-MM-DD
‘==============================================================================
Option Explicit
‘=== 設定項目 ===============================================================
Dim strComputer : strComputer = “.” ‘ “.” はローカルPCを指します。リモートPCの場合はPC名やIPアドレスを指定してください。
Dim objWMIService
Dim colItems
Dim objItem
Dim strQueryCPU, strQueryMemory
Dim dblCPUUsage, dblMemoryUsage
‘==============================================================================
‘ WMIサービスへの接続を試みる
On Error Resume Next
Set objWMIService = GetObject(“winmgmts:\\” & strComputer & “\root\cimv2”)
If Err.Number <> 0 Then
Wscript.Echo “エラー: WMIサービスに接続できませんでした。コンピューター名または権限を確認してください。” & vbCrLf & “エラーコード: ” & Err.Number & “, 説明: ” & Err.Description
Wscript.Quit(1) ‘ エラー終了
End If
On Error GoTo 0 ‘ エラーハンドリングを元に戻す
‘ CPU使用率を取得するクエリ
strQueryCPU = “SELECT LoadPercentage FROM Win32_Processor”
‘ メモリ使用率を取得するクエリ
‘ Win32_OperatingSystem クラスから TotalVisibleMemorySize と FreePhysicalMemory を取得
‘ 使用率は (TotalVisibleMemorySize – FreePhysicalMemory) / TotalVisibleMemorySize で計算
strQueryMemory = “SELECT TotalVisibleMemorySize, FreePhysicalMemory FROM Win32_OperatingSystem”
‘ — CPU使用率の取得 —
On Error Resume Next
Set colItems = objWMIService.ExecQuery(strQueryCPU)
If Err.Number <> 0 Then
Wscript.Echo “エラー: CPU使用率の取得中にエラーが発生しました。” & vbCrLf & “エラーコード: ” & Err.Number & “, 説明: ” & Err.Description
‘ CPU取得失敗でも処理を続行する (メモリ取得は可能かもしれないため)
Else
For Each objItem In colItems
dblCPUUsage = objItem.LoadPercentage
Exit For ‘ CPUは通常1つなので、最初に見つかったものでループを抜ける
Next
If IsEmpty(dblCPUUsage) Then
Wscript.Echo “警告: CPU使用率の情報が見つかりませんでした。”
Else
Wscript.Echo “CPU使用率: ” & dblCPUUsage & “%”
End If
End If
On Error GoTo 0
‘ — メモリ使用率の取得 —
On Error Resume Next
Set colItems = objWMIService.ExecQuery(strQueryMemory)
If Err.Number <> 0 Then
Wscript.Echo “エラー: メモリ使用率の取得中にエラーが発生しました。” & vbCrLf & “エラーコード: ” & Err.Number & “, 説明: ” & Err.Description
Else
For Each objItem In colItems
Dim dblTotalMemory, dblFreeMemory, dblUsedMemory
dblTotalMemory = objItem.TotalVisibleMemorySize / 1024 ‘ MB単位に変換
dblFreeMemory = objItem.FreePhysicalMemory / 1024 ‘ MB単位に変換
dblUsedMemory = dblTotalMemory – dblFreeMemory
If dblTotalMemory > 0 Then
dblMemoryUsage = (dblUsedMemory / dblTotalMemory) 100
Wscript.Echo “メモリ使用率: ” & FormatNumber(dblMemoryUsage, 2) & “% (” & FormatNumber(dblUsedMemory, 2) & “MB / ” & FormatNumber(dblTotalMemory, 2) & “MB)”
Else
Wscript.Echo “警告: メモリ使用率を計算できませんでした (TotalVisibleMemorySizeが0です)。”
End If
Exit For ‘ OSは1つなので、最初に見つかったものでループを抜ける
Next
If Not IsNumeric(dblMemoryUsage) Then ‘ 上記ループで値がセットされなかった場合
Wscript.Echo “警告: メモリ使用率の情報が見つかりませんでした。”
End If
End If
On Error GoTo 0
‘ オブジェクトの解放 (メモリリーク防止のため)
Set objItem = Nothing
Set colItems = Nothing
Set objWMIService = Nothing
Wscript.Echo “処理が完了しました。”
Wscript.Quit(0) ‘ 正常終了
【ポイント】
- エラーハンドリング (`On Error Resume Next`): WMI接続やクエリ実行時に発生する可能性のあるエラーを捕捉し、スクリプトの続行を可能にします。エラー発生時には、ユーザーに分かりやすいメッセージを表示します。
- `winmgmts:\\.\root\cimv2`: `winmgmts:` はWMIリポジトリへの接続を指定するプレフィックスです。`\.` はローカルコンピューターを指します。リモートコンピューターの場合は、`\.` の部分をコンピューター名(例: `\\Server01`)またはIPアドレス(例: `\\192.168.1.100`)に置き換えます。
- `Win32_Processor`: CPUに関する情報を管理するクラスです。`LoadPercentage` プロパティでCPU使用率を取得できます。
- `Win32_OperatingSystem`: OSに関する情報を管理するクラスです。`TotalVisibleMemorySize` (総物理メモリ量) と `FreePhysicalMemory` (空き物理メモリ量) を使用してメモリ使用率を計算します。
- オブジェクトの解放: スクリプトの最後に、使用したWMIオブジェクトを `Set … = Nothing` で明示的に解放します。これにより、不要なリソースの占有を防ぎ、メモリリークのリスクを低減します。
2. 特定プロセスの強制終了
‘==============================================================================
‘ スクリプト名: TerminateProcess.vbs
‘ 説明: 指定したプロセスID (PID) またはプロセス名を持つプロセスを強制終了する
‘ 作成者: あなたの名前
‘ 作成日: YYYY-MM-DD
‘==============================================================================
Option Explicit
‘=== 設定項目 ===============================================================
Dim strComputer : strComputer = “.” ‘ “.” はローカルPC。リモートPCの場合はPC名やIPアドレスを指定
Dim strProcessName ‘ 終了させたいプロセスの名前 (例: “notepad.exe”)
Dim strProcessID ‘ 終了させたいプロセスのPID (例: “1234”)
Dim objWMIService
Dim colProcesses
Dim objProcess
Dim bForceQuit
‘==============================================================================
‘ — 引数処理 —
If Wscript.Arguments.Count < 2 Then
Wscript.Echo "使用方法:"
Wscript.Echo " cscript " & Wscript.ScriptName & " <コンピューター名 or .> <プロセス名 or PID>”
Wscript.Echo “例: cscript ” & Wscript.ScriptName & ” . notepad.exe”
Wscript.Echo “例: cscript ” & Wscript.ScriptName & ” Server01 1234″
Wscript.Quit(1)
End If
strComputer = Wscript.Arguments(0)
Dim strTarget : strTarget = Wscript.Arguments(1)
If IsNumeric(strTarget) Then
strProcessID = strTarget
Else
strProcessName = strTarget
End If
‘ — WMIサービスへの接続 —
On Error Resume Next
Set objWMIService = GetObject(“winmgmts:\\” & strComputer & “\root\cimv2”)
If Err.Number <> 0 Then
Wscript.Echo “エラー: WMIサービスに接続できませんでした。コンピューター名または権限を確認してください。” & vbCrLf & “エラーコード: ” & Err.Number & “, 説明: ” & Err.Description
Wscript.Quit(1)
End If
On Error GoTo 0
‘ — プロセスの検索と終了 —
Dim strQuery
If Not IsEmpty(strProcessName) Then
‘ プロセス名で検索する場合
strQuery = “SELECT FROM Win32_Process WHERE Name = ‘” & strProcessName & “‘”
ElseIf Not IsEmpty(strProcessID) Then
‘ プロセスIDで検索する場合
strQuery = “SELECT FROM Win32_Process WHERE ProcessId = ” & strProcessID
End If
On Error Resume Next
Set colProcesses = objWMIService.ExecQuery(strQuery)
If Err.Number <> 0 Then
Wscript.Echo “エラー: プロセスの検索中にエラーが発生しました。” & vbCrLf & “エラーコード: ” & Err.Number & “, 説明: ” & Err.Description
Set objWMIService = Nothing ‘ オブジェクト解放
Wscript.Quit(1)
End If
On Error GoTo 0
bForceQuit = False ‘ 強制終了フラグ
If colProcesses.Count = 0 Then
If Not IsEmpty(strProcessName) Then
Wscript.Echo “情報: 指定されたプロセス名 ‘” & strProcessName & “‘ のプロセスは見つかりませんでした。”
ElseIf Not IsEmpty(strProcessID) Then
Wscript.Echo “情報: 指定されたプロセスID ” & strProcessID & ” のプロセスは見つかりませんでした。”
End If
Else
For Each objProcess In colProcesses
Dim objResult
‘ Terminateメソッドでプロセスを終了させる
‘ 戻り値は0なら成功、それ以外はエラーコード
objResult = objProcess.Terminate()
If IsArray(objResult) Then
If objResult(0) = 0 Then
Wscript.Echo “成功: プロセスID ” & objProcess.ProcessId & ” (” & objProcess.Name & “) を終了しました。”
bForceQuit = True
Else
Wscript.Echo “エラー: プロセスID ” & objProcess.ProcessId & ” (” & objProcess.Name & “) の終了に失敗しました。エラーコード: ” & objResult(0)
End If
Else
‘ Terminateメソッドの戻り値が配列でない場合 (通常は配列)
Wscript.Echo “警告: プロセスID ” & objProcess.ProcessId & ” (” & objProcess.Name & “) の終了処理で予期しない結果が得られました。”
End If
Next
End If
‘ オブジェクトの解放
Set objProcess = Nothing
Set colProcesses = Nothing
Set objWMIService = Nothing
If bForceQuit Then
Wscript.Echo “処理が正常に完了しました。”
Wscript.Quit(0)
Else
Wscript.Echo “処理が完了しましたが、指定されたプロセスは終了されませんでした。”
Wscript.Quit(0) ‘ 終了されなかった場合も、エラー終了ではなく正常終了として扱う
End If
【ポイント】
- 引数処理: `Wscript.Arguments` を使用して、スクリプト実行時にコンピューター名とプロセス名(またはPID)を渡せるようにしています。これにより、スクリプトを汎用的に利用できます。
- `Win32_Process` クラス: システム上で実行されているプロセスに関する情報を管理します。
- `ProcessId` プロパティ: プロセスのユニークなIDです。
- `Name` プロパティ: プロセスの実行ファイル名です。
- `Terminate()` メソッド: プロセスを強制終了させるメソッドです。このメソッドは、終了処理が成功したかどうかを示す戻り値(通常は0)を配列で返します。
- PIDとプロセス名の使い分け: PIDはユニークですが、プロセスが再起動すると変化する可能性があります。プロセス名は複数存在する場合もありますが、一般的にはプロセスを識別しやすい方法です。どちらの方法でもプロセスを特定し、終了させることができます。
- リモート実行の注意点: リモートPCでプロセスを終了させるには、実行するユーザーが対象PCに対する「リモート管理」および「プロセス操作」の権限を持っている必要があります。
3. サービスの再起動
‘==============================================================================
‘ スクリプト名: RestartService.vbs
‘ 説明: 指定したサービスをリモートPCで再起動する
‘ 作成者: あなたの名前
‘ 作成日: YYYY-MM-DD
‘==============================================================================
Option Explicit
‘=== 設定項目 ===============================================================
Dim strComputer : strComputer = “.” ‘ “.” はローカルPC。リモートPCの場合はPC名やIPアドレスを指定
Dim strServiceName ‘ 再起動したいサービス名 (例: “Spooler” – プリンターのスプーラーサービス)
Dim objWMIService
Dim objService
Dim objServiceSet
Dim strQuery
‘==============================================================================
‘ — 引数処理 —
If Wscript.Arguments.Count < 2 Then
Wscript.Echo "使用方法:"
Wscript.Echo " cscript " & Wscript.ScriptName & " <コンピューター名 or .> <サービス名>”
Wscript.Echo “例: cscript ” & Wscript.ScriptName & ” . Spooler”
Wscript.Echo “例: cscript ” & Wscript.ScriptName & ” Server01 W3SVC” ‘ Webサーバーサービス (IIS)
Wscript.Quit(1)
End If
strComputer = Wscript.Arguments(0)
strServiceName = Wscript.Arguments(1)
‘ — WMIサービスへの接続 —
On Error Resume Next
Set objWMIService = GetObject(“winmgmts:\\” & strComputer & “\root\cimv2”)
If Err.Number <> 0 Then
Wscript.Echo “エラー: WMIサービスに接続できませんでした。コンピューター名または権限を確認してください。” & vbCrLf & “エラーコード: ” & Err.Number & “, 説明: ” & Err.Description
Wscript.Quit(1)
End If
On Error GoTo 0
‘ — サービス名のクエリ —
‘ Win32_Service クラスから指定されたサービス名を持つものを検索
strQuery = “SELECT FROM Win32_Service WHERE Name = ‘” & strServiceName & “‘”
On Error Resume Next
Set objServiceSet = objWMIService.ExecQuery(strQuery)
If Err.Number <> 0 Then
Wscript.Echo “エラー: サービス ‘” & strServiceName & “‘ の検索中にエラーが発生しました。” & vbCrLf & “エラーコード: ” & Err.Number & “, 説明: ” & Err.Description
Set objWMIService = Nothing
Wscript.Quit(1)
End If
On Error GoTo 0
If objServiceSet.Count = 0 Then
Wscript.Echo “エラー: 指定されたサービス名 ‘” & strServiceName & “‘ のサービスが見つかりませんでした。”
Set objWMIService = Nothing
Wscript.Quit(1)
End If
‘ — サービスの状態確認と再起動 —
Dim blnStarted
Dim lngReturn
For Each objService In objServiceSet
‘ サービスの現在の状態を確認
‘ 0 = Unknown, 1 = Starting, 2 = Local Stop Pending, 3 = Stop Pending, 4 = Stopped, 5 = Stopping, 6 = Running, 7 = Continue Pending, 8 = Pause Pending, 9 = Paused
Dim intState : intState = objService.State
Wscript.Echo “サービス ‘” & objService.DisplayName & “‘ (Name: ” & objService.Name & “) の現在の状態: ” & intState
If intState = 4 Then ‘ サービスが停止している場合
Wscript.Echo “サービスは停止しています。開始を試みます…”
lngReturn = objService.StartService() ‘ サービスを開始
If lngReturn <> 0 Then
Wscript.Echo “エラー: サービス ‘” & objService.DisplayName & “‘ の開始に失敗しました。エラーコード: ” & lngReturn
Else
Wscript.Echo “サービス ‘” & objService.DisplayName & “‘ を正常に開始しました。”
End If
ElseIf intState = 6 Then ‘ サービスが実行中の場合
Wscript.Echo “サービスは実行中です。再起動を試みます…”
‘ サービスを停止
lngReturn = objService.StopService()
If lngReturn <> 0 Then
Wscript.Echo “エラー: サービス ‘” & objService.DisplayName & “‘ の停止に失敗しました。エラーコード: ” & lngReturn
Else
‘ 停止完了まで少し待つ (必要に応じて調整)
Wscript.Sleep 2000 ‘ 2秒待機
‘ サービスを開始
lngReturn = objService.StartService()
If lngReturn <> 0 Then
Wscript.Echo “エラー: サービス ‘” & objService.DisplayName & “‘ の再開に失敗しました。エラーコード: ” & lngReturn
Else
Wscript.Echo “サービス ‘” & objService.DisplayName & “‘ を正常に再起動しました。”
End If
End If
Else
Wscript.Echo “警告: サービス ‘” & objService.DisplayName & “‘ は、処理できない状態です (状態コード: ” & intState & “)。”
End If
Exit For ‘ サービスは通常1つなので、最初に見つかったものでループを抜ける
Next
‘ オブジェクトの解放
Set objService = Nothing
Set objServiceSet = Nothing
Set objWMIService = Nothing
Wscript.Echo “処理が完了しました。”
Wscript.Quit(0)
【ポイント】
- `Win32_Service` クラス: システム上で管理されているサービスに関する情報を取得・操作します。
- `Name` プロパティ: サービスの一意な名前です。これは、サービス管理ツールで表示される「表示名」とは異なる場合があります。
- `State` プロパティ: サービスの現在の状態を示します。`6` は「Running」(実行中)、`4` は「Stopped」(停止)です。
- `StartService()` メソッド: サービスを開始します。
- `StopService()` メソッド: サービスを停止します。
- `Wscript.Sleep`: サービス停止後、すぐに開始しようとすると失敗することがあります。`Wscript.Sleep` を使って一時停止することで、サービスが完全に停止するのを待つことができます。この待機時間は、環境やサービスによって調整が必要になる場合があります。
- サービス名の特定: サービス名を正確に指定することが重要です。不明な場合は、`services.msc` を開いて確認するか、以下のWMIクエリで全サービス名の一覧を取得できます。
‘ 全サービス名一覧を取得するクエリ例
‘ For Each objService In objWMIService.ExecQuery(“SELECT FROM Win32_Service”)
‘ Wscript.Echo objService.Name & ” (” & objService.DisplayName & “)”
‘ Next
ファイル・データベース連携の注意点 – 現場で「ハマる」前に知っておくべきこと
WMIスクリプトを実運用に乗せる際、ファイルやデータベースとの連携は避けて通れません。しかし、ここに落とし穴も潜んでいます。
ファイル連携
- ログ出力: WMIスクリプトの実行結果やエラー情報をファイルに記録することは、デバッグや監査の観点から非常に重要です。
- 注意点: ファイルへの書き込み権限がない、ファイルパスが存在しない、といった基本的な権限周りの問題でスクリプトが失敗することがあります。実行アカウントの権限を十分に確認してください。
- 実装例: `CreateObject(“Scripting.FileSystemObject”)` を使用し、`OpenTextFile` メソッドでログファイルを開き、`WriteLine` メソッドで追記します。
- 設定ファイル: WMIスクリプトで対象コンピューター名やサービス名などの設定を外部ファイル(INIファイルやテキストファイル)から読み込むことで、スクリプト本体の改変を最小限に抑え、保守性を向上させることができます。
- 注意点: ファイルのフォーマットが崩れると、スクリプトが正しく設定を読み込めなくなります。シンプルなキー=値形式など、解析しやすいフォーマットを採用しましょう。
データベース連携
- 結果の記録: WMIで取得した情報をデータベース(SQL Server, MySQLなど)に記録することで、長期的な傾向分析やインシデント管理に役立てることができます。
- 注意点:
- ODBC/OLE DB接続: VBScriptからデータベースに接続するには、通常ODBCドライバーやOLE DBプロバイダーを使用します。これらの設定が対象サーバーに正しくインストール・構成されている必要があります。
- 権限: データベースへの書き込み権限が必要です。
- トランザクション管理: 大量データを扱う場合、トランザクションを適切に管理しないと、パフォーマンスの低下やデータの一貫性の問題を引き起こす可能性があります。
- エラーハンドリング: データベース接続エラー、クエリ実行エラーなど、様々なエラーが発生し得ます。これらのエラーを検知し、適切に処理するロジックが不可欠です。
- 実装例 (ADO): VBScriptからデータベースに接続する最も一般的な方法は、ADO (ActiveX Data Objects) を使用することです。
‘ ADO接続の基本的な例 (SQL Serverの場合)
Dim objConnection, objRecordset
Dim strConnectionString, strSQL
‘ 接続文字列 (環境に合わせて変更してください)
strConnectionString = “Provider=SQLOLEDB;Server=YourServerName;Database=YourDatabaseName;Uid=YourUsername;Pwd=YourPassword;”
‘ SQLクエリ (例: WMIで取得したCPU使用率を挿入)
strSQL = “INSERT INTO CpuUsageLog (ComputerName, Usage, Timestamp) VALUES (‘” & strComputer & “‘, ” & dblCPUUsage & “, GETDATE())”
On Error Resume Next
Set objConnection = CreateObject(“ADODB.Connection”)
objConnection.Open strConnectionString
If Err.Number <> 0 Then
Wscript.Echo “データベース接続エラー: ” & Err.Description
‘ エラー処理
Wscript.Quit(1)
End If
On Error GoTo 0
On Error Resume Next
Set objRecordset = objConnection.Execute(strSQL)
If Err.Number <> 0 Then
Wscript.Echo “SQL実行エラー: ” & Err.Description
‘ エラー処理
Else
Wscript.Echo “データベースにCPU使用率を記録しました。”
End If
On Error GoTo 0
‘ オブジェクト解放
If Not objConnection Is Nothing Then objConnection.Close
Set objRecordset = Nothing
Set objConnection = Nothing
バグの起きない堅牢な設計のために – リーダーからの最終提言
ここまで、WMIを使ったスクリプトの例と注意点を見てきました。しかし、現場で実際に動く「堅牢な」スクリプトを開発するためには、さらに踏み込んだ設計思想が必要です。
1. 「実行者」を意識した設計: スクリプトは誰が、どのような権限で実行するのか?システムアカウントでタスクスケジューラ実行するのか、ユーザーが手動で実行するのかによって、必要な権限やエラーハンドリングのレベルが変わります。
2. 「冪等性(べきとうせい)」の追求: 同じ操作を何度実行しても、結果が常に同じになるように設計します。例えば、サービスを「再起動」する際に、既に実行中であれば開始処理をスキップする、停止中であれば再開処理をスキップするなど、状態遷移を考慮したロジックが重要です。
3. 「可読性」と「保守性」の担保:
- コメント: コードの意図を明確にするコメントは必須です。特に、WMIクエリや複雑なロジックには詳細な説明を加えましょう。
- 変数名: 意味のある、分かりやすい変数名を使用します。
- モジュール化: 共通処理は関数化し、再利用性を高めます。
- 設定値の分離: マジックナンバー(コード中に直接記述された数値や文字列)を避け、定数や設定ファイルで管理します。
4. 「パフォーマンス」への配慮:
- `ExecQuery` の最適化: `SELECT ` ではなく、必要なプロパティだけを指定します (`SELECT LoadPercentage FROM Win32_Processor`)。
- オブジェクトの早期解放: 不要になったWMIオブジェクトは、速やかに解放します (`Set obj = Nothing`)。
- リモート実行の頻度: リモートWMIコールはネットワーク帯域を消費し、遅延も発生します。頻繁すぎる実行は避け、必要最低限に留めましょう。
5. 「テスト」の徹底: 開発環境だけでなく、ステージング環境や、可能であれば本番環境に近い環境で、様々なシナリオ(正常系、異常系、境界値)を想定したテストを繰り返し行います。
まとめ
WMIとVBScriptを組み合わせることで、インフラ管理の多くの作業を自動化し、現場の生産性を向上させることができます。本記事で紹介したコード例や設計思想は、皆さんが現場で役立つツールを開発するための「羅針盤」となるはずです。
重要なのは、単にコードを動かすだけでなく、その背後にあるオブジェクトのライフサイクル、パフォーマンスへの影響、そして「なぜそのように書くべきなのか」という理由を理解することです。これらの知識を深め、日々の業務に適用することで、皆さんのインフラ管理スキルは格段に向上するでしょう。
さあ、今日からWMIを駆使して、よりスマートなインフラ管理を実現しましょう!
