こんにちは!インフラの自動化やキッティングの現場で、「夜間に一斉にPCをシャットダウンさせたい」「リモートから安全に再起動をかけたい」と思ったことはありませんか?
マクロの記録や単純なバッチファイル(`shutdown /s`など)から一歩進んで、「Windowsの奥深く(WMI)を直接叩いて、確実かつエレガントに電源を制御する」。今回は、そんなプロフェッショナルなインフラ管理の第一歩を、VBScriptを使って一緒にマスターしていきましょう。
ここをクリアすれば、Windows管理の裏側で何が起きているのかの解像度がグッと上がります。それでは、極限の知見を詰め込んだ世界へご案内します!
—
1. なぜ「WMIの Win32Shutdown」なのか?
通常のコマンドプロンプトで使える `shutdown` コマンドも便利ですが、ネットワーク越し(リモート)の制御や、実行権限の厳密な管理、そして「本当に安全にプロセスを終了させてから落とす」という点において、WMI(Windows Management Instrumentation)を経由した制御は、エンタープライズ環境のデファクトスタンダードです。
特に `Win32_OperatingSystem` クラスの `Win32Shutdown` メソッドを使うと、単なる強制終了だけでなく、次のような細かい挙動の制御が可能になります。
- フラグ(第1引数)の組み合わせによる多彩な動作
- `0`: ログオフ(Logoff)
- `2`: シャットダウン(Shutdown)
- `6`: 再起動(Reboot)
- `4`: 電源OFF(Power off)
- ※これらに `+ 4`(強制終了)や `+ 8`(電源切断)などのビットフラグを組み合わせて制御します。
—
2. 【実践】安全なシャットダウン・再起動スクリプト
それでは早速、実際のコードを見てみましょう。
メモ帳を開いて以下のコードを貼り付け、拡張子を `.vbs`(例: `remote_shutdown.vbs`)として保存してください。
‘ ==============================================================================
‘ スクリプト名: RemotePowerControl.vbs
‘ 概要: WMI経由でローカルまたはリモートPCのシャットダウン/再起動を制御する
‘ 著者: シニアインフラエンジニア
‘ ==============================================================================
Option Explicit
‘ — 設定エリア —
Dim targetComputer
targetComputer = “.” ‘ “.” はローカルPC。リモートなら “192.168.1.50” やホスト名を指定
‘ シャットダウンフラグの意味:
‘ 2 = シャットダウン
‘ 4 = 強制終了 (Force)
‘ 8 = 電源オフ (Power Off)
‘ 合計値: 2 + 4 + 8 = 14 (強制シャットダウン 兼 電源オフ)
Dim shutdownFlag
shutdownFlag = 14
‘ 理由コード (通常は 0 でOKです)
Dim reasonCode
reasonCode = 0
‘ — メイン処理 —
Call ExecuteShutdown(targetComputer, shutdownFlag, reasonCode)
‘ ==============================================================================
‘ 関数名: ExecuteShutdown
‘ 引数: strComputer (対象PC), intFlags (動作フラグ), intReason (理由)
‘ 概要: 指定されたPCに対してWMI経由でシャットダウン命令を送信する
‘ ==============================================================================
Sub ExecuteShutdown(strComputer, intFlags, intReason)
Dim objWMIService, colOperatingSystems, objOperatingSystem
Dim intResult, msgTarget
‘ 1. 対象がローカルかリモートかでメッセージを切り替え
If strComputer = “.” Then
msgTarget = “ローカルコンピュータ”
Else
msgTarget = “リモートコンピュータ (” & strComputer & “)”
End If
WScript.Echo msgTarget & ” に対して電源制御命令を送信します…”
On Error Resume Next
‘ 2. WMIサービスへの接続 (cimv2 ネームスペース)
‘ ※リモート操作の場合、ファイアウォールや管理者権限の壁を越える必要があります
Set objWMIService = GetObject(“winmgmts:{impersonationLevel=impersonate,(Shutdown)}!\\” & strComputer & “\root\cimv2”)
If Err.Number <> 0 Then
WScript.Echo “[エラー] WMIサービスへの接続に失敗しました。” & vbCrLf & _
“エラー番号: ” & Hex(Err.Number) & ” – ” & Err.Description & vbCrLf & _
“【ヒント】管理者権限の不足、ネットワーク疎通、またはRPC/ファイアウォールの設定を確認してください。”
Exit Sub
End If
On Error GoTo 0
‘ 3. Win32_OperatingSystem コレクションの取得
Set colOperatingSystems = objWMIService.InstancesOf(“Win32_OperatingSystem”)
‘ 4. 取得したOSインスタンスに対して Win32Shutdown メソッドを実行
For Each objOperatingSystem in colOperatingSystems
‘ メソッドの実行 (戻り値が 0 なら成功)
intResult = objOperatingSystem.Win32Shutdown(intFlags, intReason)
If intResult = 0 Then
WScript.Echo “[成功] ” & msgTarget & ” の電源制御コマンドが正常に受け付けられました。”
Else
WScript.Echo “[失敗] コマンドは拒否されました。リターンコード: ” & intResult & vbCrLf & _
“【ヒント】権限不足(SeShutdownPrivilegeの欠如)などが原因の可能性があります。”
End If
Next
‘ クリーンアップ
Set colOperatingSystems = Nothing
Set objWMIService = Nothing
End Sub
—
3. コードのキモをエンジニア目線で解説!
初心者のうちは魔法の呪文に見えるかもしれませんが、重要なポイントはたったの3つです。ここを押さえればVBScriptのWMI操作は怖くありません。
① 特権(Privilege)のモンタージュ:`{impersonationLevel=impersonate,(Shutdown)}`
Set objWMIService = GetObject(“winmgmts:{impersonationLevel=impersonate,(Shutdown)}!\\” & strComputer & “\root\cimv2”)
ここがこのスクリプトの最も重要な心臓部です。
Windowsでシャットダウンや再起動を行うには、プロセスに「シャットダウン特権(SeShutdownPrivilege)」という特別な通行手形が必要です。
モンタージュ(接続文字列)の中に `(Shutdown)` と明示的に書き込むことで、WMIに対して「これからOSを落とす権限を使うからよろしく!」と伝えているのです。これを忘れると、権限エラー(リターンコード等)で跳ね返されてしまいます。
② コレクションとインスタンスの概念
WMIの世界では、コンピュータの状態はすべて「オブジェクト」として管理されています。
`Win32_OperatingSystem` は、その名の通り「今動いているオペレーティングシステムそのもの」を表します。通常は1台のPCに1つですが、WMIの仕様上「コレクション(リスト)」として返ってくるため、`For Each` で回してメソッドを叩くのが作法となります。
③ 戻り値(Return Code)の確認
`Win32Shutdown` メソッドは、実行結果を数値(Integer)で返します。
- `0`:成功(Success)
- その他(非ゼロ):失敗(アクセス拒否やパラメータ不正など)
自動化スクリプトを書くときは、この戻り値をちゃんとハンドリングしてログに残すのが、プロのエンジニアの嗜みです。
—
4. 陥りやすい罠とエラーシューティング
「よし、リモートPCのIPを入れて実行だ!」と意気込んだ初学者が、必ずと言っていいほどハマる壁があります。ここで先回りして解決しておきましょう。
罠1:エラー 0x80070005 (アクセスが拒否されました / Access Denied)
- 原因: スクリプトを実行しているユーザーに、リモートPCの管理者権限がありません。または、UAC(ユーザーアカウント制御)やネットワーク越しの権限昇格の制限に引っかかっています。
- 対策:
1. VBScriptを実行するコマンドプロンプト(あるいはWScript)を「管理者として実行」してください。
2. リモートPC側のファイアウォールで、WMI(Windows Management Instrumentation)トラフィックが許可されていることを確認してください。
罠2:リモートコンピュータの名前解決・疎通エラー
- 原因: `targetComputer` に指定したホスト名やIPアドレスに届いていない、またはDNSの名前解決に失敗しています。
- 対策: 事前に `ping` コマンドで疎通が取れるか、またリモートマシンのファイアウォール(TCP 135番ポートや動的RPCポート)が空いているかを確認しましょう。
—
ここをクリアすれば、VBScriptの基本はバッチリですよ!
お疲れ様でした!今回はWMIというWindowsの深層領域にアクセスし、電源制御というインフラの根幹をVBScriptで操作する方法を解説しました。
一見難しそうに見えるWMIの構文も、「接続文字列で特権を渡し、オブジェクトを取得して、メソッドを叩く」という型さえ覚えてしまえば、プロセス管理やサービス制御、ハードウェア情報の収集など、他のあらゆる管理タスクに応用が利きます。
マクロの記録から脱却し、インフラを意のままに操るエンジニアとしての第一歩を、ぜひこのスクリプトで踏み出してみてください。あなたの自動化ライフがより豊かになることを応援しています!
