この記事は、Windowsの管理情報にアクセスするための仕組みであるWMI(Windows Management Instrumentation)を、VBScript(.vbs)を使って扱う方法を初心者向けにわかりやすく解説します。
WMIは、Windowsの管理タスクを自動化するための強力なフレームワークであり、リモート管理や、システム情報の取得などに便利です。
基本的な概念、実行方法、サンプルコード、よくあるエラーの対処、最後に演習問題とその解答例を用意しています。
対象読者は、VBScriptの基本(変数、ループ、基本的なオブジェクト操作)が分かる人。OSはWindows(Windows 7以降)を想定しています。
WMIとは何か
WMIは、Windowsに組み込まれた管理情報の提供インターフェースです。
ハードウェア、OS、プロセス、サービス、ディスク、ネットワークなど多くの項目にアクセスできます。プログラムやスクリプトからこれらの情報を取得・操作できるため、システム管理や監視に便利です。
WMIはCOMベースで動作しているため、VBScriptのようなCOMを扱えるスクリプト言語から手軽に利用できます。
実行の準備(cscript/wscript、権限)
cscript と wscript の違い
- cscript.exe: コマンドラインで実行し、標準出力(コンソール)に結果を出す。ログや出力をファイルにリダイレクトしやすいので学習や運用スクリプトに向いています。
- wscript.exe: GUI(ダイアログ)ベースで実行。メッセージボックス(MsgBox)を使うスクリプト向け。
学習・実行結果の確認には cscript を使うことをおすすめします。
コマンド例
C:\> cscript //nologo script.vbs
//nologo は余計なヘッダを表示しないオプションです。
権限
一部のWMI操作(サービスの開始/停止、リモート操作、特定のハードウェア情報取得など)は管理者権限が必要です。
管理者としてコマンドプロンプトを開いて実行するか、UACに応じた権限昇格が必要です。
VBScriptからWMIへ接続する基本コード
VBScriptでWMIに接続する代表的な書き方は以下です。
' ローカルのWMIに接続
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
' リモート接続の例(ユーザー名/パスワードを使う)
' Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate,(authenticationLevel=PktPrivacy)}\\\\REMOTEHOST\root\cimv2:"
' Set objWMIService = objWMIService.ConnectServer("REMOTEHOST", "root\cimv2", "username", "password")
winmgmts:\\.\root\cimv2 は最もよく使われるネームスペースです。GetObject でWMIサービスのルートに接続します。
クエリ例(WMIのクラスを列挙)
Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_OperatingSystem")
For Each objItem In colItems
WScript.Echo objItem.Caption
Next
主要なWMIクラス(初心者がよく使うクラス)
- Win32_OperatingSystem: OSの名称、バージョン、インストール日など
- Win32_ComputerSystem: コンピュータ名、ユーザー名、合計物理メモリなど
- Win32_LogicalDisk: 各論理ドライブの容量、空き容量、ドライブの種類
- Win32_Process: 実行中のプロセス情報(名前、PID、メモリ使用量)
- Win32_Service: Windowsサービスの状態(開始/停止/自動/手動)
- Win32_NetworkAdapterConfiguration: IPアドレスやDNS情報
これらはスクリプトで情報収集や簡単な自動化に非常に便利です。
実用的なサンプル
以下は学習で使える安全なサンプル集です。
各スクリプトはテキストファイルに保存し、.vbs 拡張子で実行してください(cscript //nologo ファイル.vbs)。
サンプル1: OS情報を取得する
Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
Set colOS = objWMI.ExecQuery("SELECT * FROM Win32_OperatingSystem")
For Each os In colOS
WScript.Echo "Caption: " & os.Caption
WScript.Echo "Version: " & os.Version
WScript.Echo "BuildNumber: " & os.BuildNumber
WScript.Echo "LastBootUpTime: " & os.LastBootUpTime
Next
サンプル2: 論理ディスクの一覧(空き容量をMBで表示)
Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
Set colDisks = objWMI.ExecQuery("SELECT DeviceID, FreeSpace, Size, FileSystem FROM Win32_LogicalDisk WHERE DriveType=3")
For Each disk In colDisks
If Not IsNull(disk.FreeSpace) Then
freeMB = Int(disk.FreeSpace / 1024 / 1024)
sizeMB = Int(disk.Size / 1024 / 1024)
Else
freeMB = "N/A"
sizeMB = "N/A"
End If
WScript.Echo disk.DeviceID & " " & freeMB & "MB free / " & sizeMB & "MB total (" & disk.FileSystem & ")"
Next
サンプル3: 実行中のプロセス一覧(名前とPID)
Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
Set procs = objWMI.ExecQuery("SELECT Name, ProcessId FROM Win32_Process")
For Each p In procs
WScript.Echo p.ProcessId & " - " & p.Name
Next
サンプル4: プロセスを新しく起動する(例: notepad.exe)
Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
Set procClass = objWMI.Get("Win32_Process")
errReturn = procClass.Create("notepad.exe", Null, Null, intProcessID)
If errReturn = 0 Then
WScript.Echo "Notepad started. PID=" & intProcessID
Else
WScript.Echo "Failed to start process. Error code: " & errReturn
End If
よくあるエラーと対処法
- 接続エラー(GetObjectが失敗する): ネームスペースのスペルミスやサービス(WMIサービス)が停止している可能性があります。サービス管理ツールで Windows Management Instrumentation サービスを確認してください。
- 権限エラー: 一部の情報は管理者権限でないと取得できません。管理者として実行してください。
- リモート接続の失敗: ネットワーク、ファイアウォール、資格情報、DCOM設定が影響します。最初はローカルで動かしてからリモートに挑戦しましょう。
- Null/IsNullエラー: WMIのプロパティに値が入っていない場合があります。IsNull()でチェックしましょう。
セキュリティと実行上の注意点
- WMIは強力な管理インターフェースです。不適切な操作(サービスの停止、プロセスの強制終了、設定変更)はシステムに影響を与えるため、テスト環境で確認してから本番で実行してください。
- リモートでのWMI操作は認証情報を扱います。パスワードのハードコーディングは避け、必要な最小権限のアカウントを使用してください。
演習問題(初級編)
下の問題は、実際にVBScriptを書いてWMIを使う練習になります。すべてローカルのWindowsで cscript //nologo ファイル.vbs を使って確認してください。
問題1: OSの情報を1行で出力する
Win32_OperatingSystem から OS名(Caption)とバージョン(Version)を取得し、フォーマットして1行で表示するスクリプトを作成してください。
出力例
Windows 10 Pro - Version 10.0.19041
Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
Set colOS = objWMI.ExecQuery("SELECT Caption, Version FROM Win32_OperatingSystem")
For Each os In colOS
WScript.Echo os.Caption & " - Version " & os.Version
Next
問題2: Cドライブの空き容量をGBで表示する
Win32_LogicalDisk を使い、DeviceID = “C:” のドライブのFreeSpaceをGB単位(小数点第2位まで)で表示するスクリプトを書いてください。値が取得できない場合は「情報なし」と表示してください。
Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
Set colDisks = objWMI.ExecQuery("SELECT DeviceID, FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='C:'")
For Each d In colDisks
If IsNull(d.FreeSpace) Then
WScript.Echo "C: - 情報なし"
Else
freeGB = Round(d.FreeSpace / 1024 / 1024 / 1024, 2)
WScript.Echo "C: - FreeSpace: " & freeGB & " GB"
End If
Next
' Round 関数が無い場合の互換処理
Function Round(num, decimals)
scale = 10 ^ decimals
Round = Int(num * scale + 0.5) / scale
End Function
問題3: 指定したプロセス名が実行中かチェックする
引数(コマンドライン引数)でプロセス名(例: notepad.exe)を受け取り、該当プロセスが見つかれば「実行中(PID: xxx)」、見つからなければ「実行していません」と表示するスクリプトを作成してください。
If WScript.Arguments.Count = 0 Then
WScript.Echo "使い方: cscript //nologo checkproc.vbs プロセス名.exe"
WScript.Quit
End If
procName = WScript.Arguments(0)
Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
Set procs = objWMI.ExecQuery("SELECT Name, ProcessId FROM Win32_Process WHERE Name='" & procName & "'")
found = False
For Each p In procs
WScript.Echo "実行中 (PID: " & p.ProcessId & ")"
found = True
Next
If Not found Then
WScript.Echo "実行していません"
End If
問題4: サービスの開始状態を取得する
Win32_Service から Name = “wuauserv”(Windows Update サービス)の State を取得し、現在の状態を表示するスクリプトを作ってください(例: Running, Stopped)。管理者権限が必要となる場合があります。
Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
Set services = objWMI.ExecQuery("SELECT Name, State FROM Win32_Service WHERE Name='wuauserv'")
For Each s In services
WScript.Echo "Service: " & s.Name & " - State: " & s.State
Next
問題5: 起動スクリプト(応用)
notepad.exe を起動し、起動後にそのプロセスのPIDを表示するスクリプトを作成してください。起動に失敗した場合はエラーコードを表示してください。
Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
Set procClass = objWMI.Get("Win32_Process")
errReturn = procClass.Create("notepad.exe", Null, Null, intProcessID)
If errReturn = 0 Then
WScript.Echo "Notepad started. PID=" & intProcessID
Else
WScript.Echo "Failed to start process. Error code: " & errReturn
End If
