こんにちは。自動化の現場でVBScriptと長年戦ってきたエンジニアです。
皆さんは、運用監視の現場で「このサーバー、最後にいつ再起動されたんだろう?」と悩んだことはありませんか?GUIのタスクマネージャーを開くのも良いですが、自動化エンジニアとしては、「スクリプト一発で、OSの稼働時間を秒単位で弾き出す」という美学を追求したいところです。
今回は、WMI(Windows Management Instrumentation)というWindowsの心臓部に触れ、`LastBootUpTime` を料理する方法を伝授します。これさえマスターすれば、VBScriptの「日付データの不自由さ」を克服する力が身につきますよ。
—
1. WMIの「異質な時間形式」を解読せよ
Windows内部で使われているWMIの日付形式は、`CIM_DATETIME` と呼ばれる特殊な文字列です。例えば `20231027103000.000000+540` のような形式で返ってきます。
- 2023(年)10(月)27(日)10(時)30(分)00(秒)…
人間には読めますが、VBScriptの計算エンジンである `Date` 型は、このままでは理解できません。我々の仕事は、この文字列を「切り刻んで」、`DateSerial` 関数などが扱える形式へ再構築することです。
2. 稼働時間算出のロジックを実装する
では、実際にOSの最終起動日時を取得し、現在時刻との差分(=稼働時間)を算出するスクリプトを見てみましょう。
‘ WMI経由でOS稼働時間を算出するスクリプト
Option Explicit
Dim objWMIService, objOS, colOS
Dim strBootDate, dtBootDate, dtNow, tsUptime
‘ 1. WMIサービスへ接続(ローカルホスト)
Set objWMIService = GetObject(“winmgmts:\\.\root\cimv2”)
Set colOS = objWMIService.ExecQuery(“Select from Win32_OperatingSystem”)
For Each objOS in colOS
‘ 2. CIM_DATETIME形式の文字列を取得 (例: 20231027…)
strBootDate = objOS.LastBootUpTime
‘ 3. 文字列を解析してDate型へ変換する関数を呼び出し
dtBootDate = WMIDateToDate(strBootDate)
dtNow = Now()
‘ 4. 差分計算(DateDiffで分単位を取得)
tsUptime = DateDiff(“n”, dtBootDate, dtNow)
WScript.Echo “最終起動日時: ” & dtBootDate
WScript.Echo “現在時刻 : ” & dtNow
WScript.Echo “連続稼働時間: ” & tsUptime & ” 分 (” & Round(tsUptime / 1440, 2) & ” 日)”
Next
‘ ———————————————————
‘ WMIの日付文字列をVBScript標準のDate型に変換する関数
‘ ———————————————————
Function WMIDateToDate(wmiDate)
Dim yyyy, mm, dd, hh, min, ss
‘ 文字列の特定位置をスライスして抽出
yyyy = Mid(wmiDate, 1, 4)
mm = Mid(wmiDate, 5, 2)
dd = Mid(wmiDate, 7, 2)
hh = Mid(wmiDate, 9, 2)
min = Mid(wmiDate, 11, 2)
ss = Mid(wmiDate, 13, 2)
‘ DateSerialでDate型へ構築
WMIDateToDate = DateSerial(yyyy, mm, dd) + TimeSerial(hh, min, ss)
End Function
—
3. このコードで押さえておくべき「3つのポイント」
① `Mid` 関数の活用
WMIの日付は桁数が固定されています。`Mid(str, start, length)` を使うことで、年・月・日を正確に切り出せます。これはVBScriptにおける文字列操作の基本中の基本です。
② `DateSerial` と `TimeSerial` の組み合わせ
日付データを作るときは、`DateSerial(年, 月, 日)` に `TimeSerial(時, 分, 秒)` を足し合わせるのが最も安全です。浮動小数点ベースで計算するよりも、直感的に日付オブジェクトを生成できます。
③ なぜ `DateDiff` を使うのか?
`Now – dtBootDate` と引き算をしてはいけません。VBScriptにおいて日付の引き算を行うと、結果は「日数」になりますが、時間や分単位で正確にハンドリングしたい場合は `DateDiff` 関数を使うのが「プロの作法」です。
—
初学者が陥りやすい罠:エラーハンドリングの重要性
現場でこのコードを使う際、「WMIが反応しない」というケースに遭遇することがあります。
- 権限不足: WMIは管理者権限を要求するクエリが多いです。実行時は必ず「管理者として実行」を意識してください。
- WMIリポジトリの破損: 滅多にありませんが、特定の環境では `GetObject` がタイムアウトします。`On Error Resume Next` を使い、`If Err.Number <> 0 Then` でエラーを拾う習慣をつけましょう。
最後に:自動化エンジニアの心構え
今回作成したスクリプトは、ただの「稼働時間計算機」ではありません。これは「システムの状態を可視化するセンサー」の第一歩です。
ここから、さらに「稼働時間が30日を超えていたらアラートメールを飛ばす」といった機能を追加すれば、立派な運用ツールになります。VBScriptは古い言語だと言われますが、WindowsというOSの深淵を覗くための最高のツールであることに変わりはありません。
ぜひ、このコードを自分の環境で動かし、改造してみてください。動いた時の小さな感動こそが、エンジニアとしての最大の報酬ですよ!
