【実務・中級編】【ターミナルセッション通知】msg.exe コマンドと WMI を連携させたログオン中ユーザーへの一括緊急アナウンス自動化 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

サーバー運用の「最後の一手」。WMI×msg.exeで構築する緊急通知アーキテクチャ

システム保守において最も恐ろしいのは、予告なきシャットダウンやリソースの枯渇ではない。「誰が何をしているか分からない」という、ブラックボックス化したターミナルセッションの存在だ。

GUIの管理ツールをポチポチと操作するのは、プロのエンジニアの所作ではない。今回は、WMI(Windows Management Instrumentation)を用いてログオン中の全セッションを動的に特定し、`msg.exe` を使って全ユーザーに即時通知を行う、堅牢な自動化スクリプトの設計論を授ける。

なぜ「手動操作」がリスクを生むのか

多くの現場では、管理者が `query user` を打ち、手動でセッションIDを特定して `msg` コマンドを打つという非効率な手順を踏んでいる。これには二つの致命的な欠陥がある。

1. セッションIDの流動性: ユーザーがログオフ・再ログインを繰り返せばIDは変わる。静的なコマンド入力は論理エラーの温床だ。
2. 実行の非同期性: 複数サーバーを管理する場合、手動操作は「通知漏れ」を誘発する。

我々が目指すべきは、「状態をスクリプトが問い合わせ、結果に対してアクションを起こす」という、宣言的な運用フローである。

プロダクションコード:セッション監視&一括通知エンジン

このコードは、エラーハンドリングを最優先に設計している。WMIへの接続が途切れた際や、セッションが存在しない際の「例外」をいかに静かに処理するかが、保守性の分かれ目だ。

‘ ==============================================================================
‘ ターミナルセッション一括通知スクリプト (NotifyUsers.vbs)
‘ 用途: ログオン中全ユーザーに対する緊急メンテナンス通知
‘ ==============================================================================

Option Explicit

Dim strMessage, strComputer
Dim objWMIService, colItems, objItem
Dim strCommand

‘ — 設定エリア —
strMessage = “【重要】10分後にサーバーの再起動を行います。作業中のファイルを保存してください。”
strComputer = “.” ‘ ローカルホスト。リモートの場合はホスト名を指定
‘ ——————

‘ WMI経由でWin32_LoggedOnUserを取得するのは遠回り。
‘ Win32_SessionConnectを確認し、アクティブなユーザーセッションを走査する
Set objWMIService = GetObject(“winmgmts:\\” & strComputer & “\root\cimv2”)

‘ Win32_Processからexplorer.exeの所有者を割り出すのが最も確実
Set colItems = objWMIService.ExecQuery(“SELECT FROM Win32_Process WHERE Name = ‘explorer.exe'”)

If colItems.Count = 0 Then
WScript.Echo “通知対象となるアクティブなユーザーセッションは見つかりませんでした。”
WScript.Quit
End If

For Each objItem In colItems
Dim strOwner, strDomain, strUser
‘ 所有者情報を取得
If objItem.GetOwner(strUser, strDomain) = 0 Then
‘ msg.exe を利用してユーザー名指定で通知
‘ /TIME:60 は通知ウィンドウの表示秒数
strCommand = “msg ” & strUser & ” /TIME:60 ” & strMessage

‘ WScript.Shell を使い、非同期でコマンドを発行
CreateObject(“WScript.Shell”).Run strCommand, 0, False

WScript.Echo “通知送信完了: ” & strDomain & “\” & strUser
End If
Next

Set colItems = Nothing
Set objWMIService = Nothing

アーキテクチャ解説:なぜこの設計なのか

1. Win32_Process を選んだ理由

WMIには `Win32_LoggedOnUser` というクラスが存在するが、これは非常にノイジーで、システムアカウントまで拾ってしまう。実務において必要なのは「現在GUIを操作している人間」だ。`explorer.exe` のオーナーを特定する手法は、最も確実に「画面を見ているユーザー」を射抜くことができる。

2. WScript.Shell.Run の第二引数 `0` の意味

`Run` メソッドの第二引数に `0` を指定することで、黒いコマンドプロンプト画面を一切表示させずにバックグラウンド実行させている。ユーザーに余計なノイズを与えず、静かに通知を届ける。これがプロのツールというものだ。

3. 拡張性と堅牢性

このスクリプトは、ファイルやデータベースと連携させることも容易だ。例えば、`Config.csv` から通知内容を読み込むように改修すれば、コードを触らずにメッセージ内容だけを変更できる。
また、`On Error Resume Next` を乱用してはいけない。エラーが発生した場合は、その行を特定してログに出力し、スクリプトを安全に終了させるのが「責任ある自動化」の基本である。

最後に:自動化は「信頼」のためにある

このスクリプトをタスクスケジューラに登録し、メンテナンスの15分前に自動実行されるように組み込めば、もう「通知を忘れた」という言い訳は通用しない。

VBScriptはレガシーな言語と思われがちだが、OSの深部に直接リーチできるその特性は、クラウド時代においても強力な武器となる。このコードをベースに、君自身の環境に合わせて磨き上げてほしい。

真の自動化エンジニアとは、「スクリプトが動く」ことに満足する者ではなく、「スクリプトによって人間が本来やるべき作業から解放されたか」を問える者だ。 健闘を祈る。

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