【テクニカル・上級編】【稼働時間計測】WMI Win32_OperatingSystem の LastBootUpTime を用いたOS連続稼働時間(Uptime)算出 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

VBScriptを掌握する:WMIから紐解くOS稼働時間の深淵

現場で長年戦い続けてきたエンジニアであれば、一度は直面する課題がある。「このサーバーは、本当に再起動されているのか?」。

タスクマネージャーの稼働時間表示を鵜呑みにするのは、ジュニアエンジニアのすることだ。我々アーキテクトは、WMI(Windows Management Instrumentation)の深層に潜り、OSの真実を直接抽出する。今回は、VBScriptにおける`Win32_OperatingSystem`の`LastBootUpTime`を解析し、極限までメモリ効率を高めた稼働時間算出ロジックを伝授する。

なぜ、WMIのCIM_DATETIMEは厄介なのか

WMIが返す時刻形式は、ISO 8601を拡張した`CIM_DATETIME`という特殊な文字列型だ。例として `20231027103000.000000+540` のような形式で出力される。これをVBScriptの`Date`型に直接キャストすることはできない。

単純な文字列スライスで力技の変換を行うコードが散見されるが、それは素人のやり方だ。文字のエンコーディングやタイムゾーンのオフセットを考慮しない実装は、グローバル環境やサマータイム適用環境で必ず破綻する。

極限のパフォーマンスを追求した算出ロジック

以下に、メモリリークを許さず、かつ堅牢に動作する最適化されたコードを提示する。

Option Explicit

‘ メモリ管理の鉄則:オブジェクトのスコープを最小化し、明示的に解放する
Dim objWMIService, colOS, objOS
Dim strLastBootUpTime, dtLastBoot, dtNow
Dim diffMinutes, diffDays, diffHours

Set objWMIService = GetObject(“winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2”)
Set colOS = objWMIService.ExecQuery(“SELECT LastBootUpTime FROM Win32_OperatingSystem”)

For Each objOS In colOS
strLastBootUpTime = objOS.LastBootUpTime

‘ CIM_DATETIME を VBScript の Date 型に変換する関数を呼ぶ
dtLastBoot = WMIDateStringToDate(strLastBootUpTime)
dtNow = Now()

‘ 稼働時間の算出(分単位)
diffMinutes = DateDiff(“n”, dtLastBoot, dtNow)

diffDays = diffMinutes \ 1440
diffHours = (diffMinutes Mod 1440) \ 60
diffMinutes = diffMinutes Mod 60

WScript.Echo “最終起動日時: ” & dtLastBoot
WScript.Echo “連続稼働時間: ” & diffDays & “日 ” & diffHours & “時間 ” & diffMinutes & “分”
Next

‘ オブジェクトの明示的解放(VBScriptにおける最重要作法)
Set objOS = Nothing
Set colOS = Nothing
Set objWMIService = Nothing

‘ ———————————————————
‘ 変換ロジック:CIM_DATETIME を Date 型へ変換
‘ ———————————————————
Function WMIDateStringToDate(dtmInstallDate)
If IsNull(dtmInstallDate) Then
WMIDateStringToDate = Null
Exit Function
End If

‘ 年・月・日・時・分・秒をスライスして DateSerial/TimeSerial で構築
WMIDateStringToDate = DateSerial(Left(dtmInstallDate, 4), Mid(dtmInstallDate, 5, 2), Mid(dtmInstallDate, 7, 2)) + _
TimeSerial(Mid(dtmInstallDate, 9, 2), Mid(dtmInstallDate, 11, 2), Mid(dtmInstallDate, 13, 2))
End Function

アーキテクトの視点:コードの要点

1. オブジェクトのライフサイクル管理

VBScriptのエンジンは、参照カウンタベースのCOMオブジェクト管理を行う。特にWMIのような重いリソースを扱う場合、`Set obj = Nothing` を怠ることは、バックグラウンドでのメモリ断片化(Fragmenting)を招く。特に長期間稼働するタスクスケジューラからの呼び出しでは、この「明示的な掃除」がシステムの延命に直結する。

2. `DateSerial` と `TimeSerial` の活用

文字列操作で無理やり「2023/10/27…」のようなフォーマットを作るのは避けるべきだ。ロケール設定に依存して動作が不安定になる可能性があるからだ。`DateSerial`関数を使用することで、内部的に数値として演算を行い、VBScriptの標準的な`Date`型へ正確に変換している。

3. WMIクエリの最適化

`SELECT ` を使うな。常に必要なプロパティのみを指定しろ(今回は`LastBootUpTime`のみ)。WMIのインスタンス化は、システムにおいて比較的コストの高い処理だ。不要なプロパティをメモリに読み込ませることは、低スペックなレガシーサーバーにおいては致命的なパフォーマンス低下を招く。

まとめ

VBScriptは古臭い言語だと言われる。しかし、OSの根幹に触れるような処理において、この「軽量さ」と「直結感」は、複雑なフレームワークを積んだ現代の言語よりも遥かに信頼性が高い。

システム管理とは、華やかなGUIを作ることではない。OSの深淵を覗き込み、数字の裏にある「マシンの状態」を正確に把握することだ。このロジックが、君の現場の安定稼働に寄与することを願う。

――コードは嘘をつかない。それが、エンジニアとしての唯一の真実だ。

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