PCの起動時間・稼働時間をバッチファイルで定期記録しておくと、障害調査や運用管理に役立ちます。本記事では wmic・net stats・PowerShell による取得方法の比較から、稼働時間の計算、ログ追記、タスクスケジューラ登録まで体系的に解説します。
- PCの起動時刻(LastBootUpTime)をバッチファイルで取得する方法
- 現在時刻 − 起動時刻で稼働時間を計算する方法
- 起動時刻・稼働時間をログファイルに自動追記する完全スクリプト
- タスクスケジューラで「ログオン時・定期実行」を自動化する手順
- wmic・systeminfo・PowerShell の使い分けと注意点
- ログが肥大化しないようローテーションする方法
取得方法の比較
| 方法 | 取得できる情報 | 特徴 |
|---|---|---|
wmic os get LastBootUpTime |
OS 起動時刻(精密) | 純バッチで扱いやすい。Windows 11 22H2 以降で非推奨 |
systeminfo |
システム起動時間(文字列) | ロケールに依存。実行に 30 秒以上かかることがある |
net stats workstation |
Workstation サービス開始時刻 | 全エディションで利用可。OS 起動時刻とわずかにずれる |
PowerShell Get-CimInstance |
起動時刻・稼働時間(計算済み) | 最も正確・将来性あり。Windows 11 推奨 |
wmic は Windows 11 22H2 以降で非推奨(deprecated)となり、将来的に削除される予定です。Windows 11 が対象の場合は PowerShell の Get-CimInstance を使うのが確実です。
方法1: wmic で起動時刻を取得する(純バッチ)
起動時刻の取得と整形
@echo off
setlocal
REM wmic から LastBootUpTime を取得
REM 出力例: 20250511064823.000000+540
for /f "skip=1 tokens=1" %%A in ('wmic os get LastBootUpTime') do (
set RAW=%%A
goto :parse
)
:parse
REM 年月日・時分秒を切り出す
set BOOT_YEAR=%RAW:~0,4%
set BOOT_MON=%RAW:~4,2%
set BOOT_DAY=%RAW:~6,2%
set BOOT_HH=%RAW:~8,2%
set BOOT_MM=%RAW:~10,2%
set BOOT_SS=%RAW:~12,2%
echo 起動時刻: %BOOT_YEAR%/%BOOT_MON%/%BOOT_DAY% %BOOT_HH%:%BOOT_MM%:%BOOT_SS%
endlocal
現在時刻も wmic で取得して整形
@echo off
setlocal
REM 現在時刻(wmic LocalDateTime は %DATE% よりロケール依存が少ない)
for /f "skip=1 tokens=1" %%A in ('wmic os get LocalDateTime') do (
set NOW_RAW=%%A
goto :parse_now
)
:parse_now
set NOW=%NOW_RAW:~0,4%/%NOW_RAW:~4,2%/%NOW_RAW:~6,2% %NOW_RAW:~8,2%:%NOW_RAW:~10,2%:%NOW_RAW:~12,2%
echo 現在時刻: %NOW%
endlocal
%DATE% は日本語環境では 2025/05/11、英語環境では Sun 05/11/2025 など形式が異なります。ログに日付を書き込む場合は wmic os get LocalDateTime か PowerShell を使う方がロケールに依存しません。
方法2: net stats workstation で起動時刻を取得
Windows の全エディション(Home 含む)で使えます。ただし、Workstation サービスの開始時刻であり、OS 起動時刻と数秒〜数分ずれる場合があります。
@echo off
setlocal
REM 英語環境: "Statistics since" / 日本語環境: "統計は"
REM findstr で OS 言語に依存しない取得を行う場合は両方を試す
for /f "tokens=2,*" %%A in ('net stats workstation ^| findstr /i "statistics since"') do (
set SINCE=%%A %%B
goto :got_since
)
REM 日本語環境向け
for /f "tokens=2,*" %%A in ('net stats workstation ^| find "統計は"') do (
set SINCE=%%A %%B
goto :got_since
)
:got_since
echo 稼働開始時刻: %SINCE%
endlocal
方法3: PowerShell で起動時刻・稼働時間を取得(推奨)
PowerShell を使うと、起動時刻と稼働時間を1行で取得できます。Windows 11 環境や wmic が使えない場合はこちらを使ってください。
起動時刻のみ取得
@echo off
REM PowerShell で起動時刻を取得してバッチ変数に格納
powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).LastBootUpTime.ToString('yyyy/MM/dd HH:mm:ss')" > "%TEMP%oot_time.txt"
set /p BOOT_TIME=< "%TEMP%oot_time.txt"
echo 起動時刻: %BOOT_TIME%
稼働時間(日・時間・分)も計算して取得
@echo off
REM 起動時刻と稼働時間を一括取得
powershell -NoProfile -Command ^
"$os = Get-CimInstance Win32_OperatingSystem;" ^
"$boot = $os.LastBootUpTime;" ^
"$uptime = (Get-Date) - $boot;" ^
"Write-Output ('BOOT=' + $boot.ToString('yyyy/MM/dd HH:mm:ss'));" ^
"Write-Output ('UPTIME=' + $uptime.Days + '日' + $uptime.Hours + '時間' + $uptime.Minutes + '分')" ^
> "%TEMP%uptime_result.txt"
REM 結果をバッチ変数に読み込む
for /f "tokens=1,* delims==" %%K in (%TEMP%uptime_result.txt) do set %%K=%%L
echo 起動時刻: %BOOT%
echo 稼働時間: %UPTIME%
稼働時間をバッチだけで計算する
wmic の起動時刻と現在時刻の差をバッチファイルのみで計算します。日をまたぐ場合の繰り下げ処理も含む実装です。
@echo off
setlocal enabledelayedexpansion
REM 起動時刻を取得
for /f "skip=1 tokens=1" %%A in ('wmic os get LastBootUpTime') do (set BOOT_RAW=%%A & goto :boot_done)
:boot_done
set /a BOOT_H=1%BOOT_RAW:~8,2% - 100
set /a BOOT_M=1%BOOT_RAW:~10,2% - 100
set /a BOOT_S=1%BOOT_RAW:~12,2% - 100
REM 現在時刻を取得
for /f "skip=1 tokens=1" %%A in ('wmic os get LocalDateTime') do (set NOW_RAW=%%A & goto :now_done)
:now_done
set /a NOW_H=1%NOW_RAW:~8,2% - 100
set /a NOW_M=1%NOW_RAW:~10,2% - 100
set /a NOW_S=1%NOW_RAW:~12,2% - 100
REM 秒単位で差を計算
set /a BOOT_TOTAL = BOOT_H*3600 + BOOT_M*60 + BOOT_S
set /a NOW_TOTAL = NOW_H*3600 + NOW_M*60 + NOW_S
set /a DIFF = NOW_TOTAL - BOOT_TOTAL
REM 日をまたいだ場合(負の値になる)
if !DIFF! LSS 0 set /a DIFF += 86400
REM 時・分・秒に変換
set /a UP_H = DIFF / 3600
set /a UP_M = (DIFF - UP_H*3600) / 60
set /a UP_S = DIFF - UP_H*3600 - UP_M*60
echo 稼働時間: !UP_H!時間 !UP_M!分 !UP_S!秒
endlocal
上記のバッチ計算は「当日中の起動」を想定しています。サーバーなど複数日にわたって稼働するケースでは PowerShell の
TimeSpan を使って日数も含めて計算する方法を推奨します。
ログファイルに記録する完全スクリプト
起動時刻・稼働時間・現在時刻をログファイルに自動追記する完全版です。PowerShell と純バッチの2バージョンを用意しました。
バージョン A: PowerShell 連携版(推奨・Windows 10/11 向け)
@echo off
setlocal
set LOGFILE=%~dp0pc_uptime_log.txt
REM PowerShell で起動時刻・稼働時間・現在時刻を取得してログに書き込む
powershell -NoProfile -Command ^
"$os = Get-CimInstance Win32_OperatingSystem;" ^
"$boot = $os.LastBootUpTime;" ^
"$now = Get-Date;" ^
"$uptime = $now - $boot;" ^
"$line = '-----------------------------------';" ^
"$line | Add-Content -Path '%LOGFILE%' -Encoding UTF8;" ^
"('記録時刻 : ' + $now.ToString('yyyy/MM/dd HH:mm:ss')) | Add-Content -Path '%LOGFILE%' -Encoding UTF8;" ^
"('起動時刻 : ' + $boot.ToString('yyyy/MM/dd HH:mm:ss')) | Add-Content -Path '%LOGFILE%' -Encoding UTF8;" ^
"('稼働時間 : ' + $uptime.Days + '日' + $uptime.Hours + '時間' + $uptime.Minutes + '分') | Add-Content -Path '%LOGFILE%' -Encoding UTF8"
echo ログを記録しました: %LOGFILE%
endlocal
バージョン B: 純バッチ版(wmic 使用・Windows 7/8/10 向け)
@echo off
setlocal enabledelayedexpansion
set LOGFILE=%~dp0pc_uptime_log.txt
REM 現在時刻を wmic から取得
for /f "skip=1 tokens=1" %%A in ('wmic os get LocalDateTime') do (set NOW_RAW=%%A & goto :now_done)
:now_done
set NOW=%NOW_RAW:~0,4%/%NOW_RAW:~4,2%/%NOW_RAW:~6,2% %NOW_RAW:~8,2%:%NOW_RAW:~10,2%:%NOW_RAW:~12,2%
REM 起動時刻を wmic から取得
for /f "skip=1 tokens=1" %%A in ('wmic os get LastBootUpTime') do (set BOOT_RAW=%%A & goto :boot_done)
:boot_done
set BOOT=%BOOT_RAW:~0,4%/%BOOT_RAW:~4,2%/%BOOT_RAW:~6,2% %BOOT_RAW:~8,2%:%BOOT_RAW:~10,2%:%BOOT_RAW:~12,2%
REM 稼働時間を計算
set /a NOW_H=1%NOW_RAW:~8,2% - 100
set /a NOW_M=1%NOW_RAW:~10,2% - 100
set /a NOW_S=1%NOW_RAW:~12,2% - 100
set /a BOOT_H=1%BOOT_RAW:~8,2% - 100
set /a BOOT_M=1%BOOT_RAW:~10,2% - 100
set /a BOOT_S=1%BOOT_RAW:~12,2% - 100
set /a DIFF = (NOW_H - BOOT_H)*3600 + (NOW_M - BOOT_M)*60 + (NOW_S - BOOT_S)
if !DIFF! LSS 0 set /a DIFF += 86400
set /a UP_H = DIFF / 3600
set /a UP_M = (DIFF - UP_H*3600) / 60
set /a UP_S = DIFF - UP_H*3600 - UP_M*60
REM ログに追記
(
echo -----------------------------------
echo 記録時刻 : %NOW%
echo 起動時刻 : %BOOT%
echo 稼働時間 : !UP_H!時間 !UP_M!分 !UP_S!秒
) >> "%LOGFILE%"
echo ログを記録しました: %LOGFILE%
endlocal
出力されるログ例
----------------------------------- 記録時刻 : 2025/05/11 17:12:33 起動時刻 : 2025/05/11 06:48:23 稼働時間 : 0日10時間24分 ----------------------------------- 記録時刻 : 2025/05/12 09:05:10 起動時刻 : 2025/05/12 08:55:02 稼働時間 : 0日0時間10分
タスクスケジューラで自動実行する
GUI から設定する手順
REM タスクスケジューラを開く taskschd.msc REM 設定のポイント REM トリガー: ユーザーのログオン時 / 起動時 / 毎日 N 時 REM 操作: プログラムの開始 → cmd.exe REM 引数: /c "C:atch ecord_uptime.bat" REM 作業フォルダ: C:atch
コマンドラインから登録する
REM ログオン時に実行するタスクを登録(管理者権限で実行) schtasks /create /tn "PCUptimeLog" ^ /tr "cmd /c "C:atch ecord_uptime.bat"" ^ /sc onlogon /ru "%USERNAME%" /f REM 毎日 09:00 に実行するタスクを追加 schtasks /create /tn "PCUptimeLogDaily" ^ /tr "cmd /c "C:atch ecord_uptime.bat"" ^ /sc daily /st 09:00 /ru "%USERNAME%" /f REM 登録内容を確認 schtasks /query /tn "PCUptimeLog" /fo list REM タスクを削除する場合 schtasks /delete /tn "PCUptimeLog" /f
タスクスケジューラから実行すると作業ディレクトリが
C:WindowsSystem32 になります。スクリプト内でログファイルのパスを相対パスで書くと意図しない場所に保存されます。%~dp0 を使ってバッチファイルと同じフォルダに保存するか、絶対パスで指定してください。
ログのローテーション・古いログの削除
@echo off
setlocal
set LOGFILE=%~dp0pc_uptime_log.txt
set MAX_LINES=500
REM ログが MAX_LINES 行を超えたら古い行を削除
for /f %%C in ('find /c /v "" ^< "%LOGFILE%"') do set LINE_COUNT=%%C
if %LINE_COUNT% GTR %MAX_LINES% (
REM 末尾 MAX_LINES 行だけ残す(PowerShell を利用)
powershell -NoProfile -Command ^
"(Get-Content '%LOGFILE%') | Select-Object -Last %MAX_LINES% | Set-Content '%LOGFILE%' -Encoding UTF8"
echo ログを %MAX_LINES% 行にトリミングしました
)
endlocal
ログの世代管理・自動削除など本格的なローテーションは バッチファイルのログローテーション実装ガイド(日付管理・自動削除・世代管理) で詳しく解説しています。
よくある落とし穴
落とし穴1: wmic が Windows 11 22H2 以降で非推奨
REM wmic os get LastBootUpTime は将来的に削除される可能性がある
REM Windows 11 環境では代わりに PowerShell を使う
REM PowerShell による代替
powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).LastBootUpTime.ToString('yyyy/MM/dd HH:mm:ss')"
落とし穴2: systeminfo は実行に時間がかかる
REM NG: systeminfo は 30 秒以上かかることがある
for /f "tokens=1,* delims=:" %%a in ('systeminfo ^| find "システム起動時間"') do set BOOT=%%b
REM OK: wmic か PowerShell を使えば 1〜2 秒で取得できる
for /f "skip=1 tokens=1" %%A in ('wmic os get LastBootUpTime') do (set RAW=%%A & goto :done)
:done
落とし穴3: net stats srv は Windows Home で動かない
REM NG: Windows Home には Server サービスが存在しない net stats srv REM → エラー: サービス名が正しくありません REM OK: net stats workstation は全エディションで動く net stats workstation | findstr /i "statistics since"
落とし穴4: wmic 出力末尾のスペース・改行コード問題
REM wmic の出力には末尾にスペースが含まれることがある
REM 変数展開で文字列切り出し(~8,2 など)を使えば影響を受けない
REM 変数の値を確認するときは [] で囲むと分かりやすい
for /f "skip=1 tokens=1" %%A in ('wmic os get LastBootUpTime') do (set RAW=%%A & goto :done)
:done
echo [%RAW%] ← 末尾にスペースや不可視文字がないか確認
よくある質問(FAQ)
LOGFILE 変数を UNC パスに変更するだけです。共有フォルダへの書き込み権限があることを確認してください。
REM LOGFILE を共有フォルダのパスに変更 set LOGFILE=\192.168.1.10logspc_uptime_%COMPUTERNAME%.log REM PC 名をファイル名に含めると複数台の記録を区別しやすい set LOGFILE=\fileserverlogs\%COMPUTERNAME%_uptime.log
CSV 形式にすることで Excel で開いて分析しやすくなります。
@echo off
setlocal
set CSVFILE=%~dp0pc_uptime.csv
REM ヘッダー行がなければ追加
if not exist "%CSVFILE%" (
echo 記録時刻,起動時刻,稼働時間 >> "%CSVFILE%"
)
REM PowerShell で値を取得して CSV に追記
powershell -NoProfile -Command ^
"$os = Get-CimInstance Win32_OperatingSystem;" ^
"$boot = $os.LastBootUpTime;" ^
"$now = Get-Date;" ^
"$up = $now - $boot;" ^
"$row = $now.ToString('yyyy/MM/dd HH:mm:ss') + ',' + $boot.ToString('yyyy/MM/dd HH:mm:ss') + ',' + $up.Days + '日' + $up.Hours + '時間' + $up.Minutes + '分';" ^
"$row | Add-Content -Path '%CSVFILE%' -Encoding UTF8"
echo CSV に記録しました: %CSVFILE%
endlocal
シャットダウン時刻は Windows のシャットダウン時に実行するバッチで現在時刻を記録します。タスクスケジューラのトリガーに「イベント」→「システム シャットダウン」を使います。
REM タスクスケジューラで「シャットダウン開始」イベントを捕捉する REM トリガー: イベント → ログ: System → ソース: User32 → イベント ID: 1074 schtasks /create /tn "PCShutdownLog" ^ /tr "cmd /c echo %COMPUTERNAME% %DATE% %TIME% >> C:logsshutdown.log" ^ /sc onevent /ec System /mo "*[System[Provider[@Name='User32'] and EventID=1074]]" ^ /ru SYSTEM /f
ログオン時・ログオフ時のタスクは一般ユーザーでも登録できます。/ru "%USERNAME%" で自分のアカウントで実行するよう指定してください。スタートアップ(起動時)タスクは管理者権限が必要です。
REM 一般ユーザーでも登録できるログオン時タスク schtasks /create /tn "PCUptimeLog" ^ /tr "cmd /c "C:atch ecord_uptime.bat"" ^ /sc onlogon /ru "%USERNAME%" /f
ログファイル名に %COMPUTERNAME% を含めることで、共有フォルダに PC ごとのログを自動で振り分けられます。
REM PC 名つきのログファイルに記録(共有フォルダ) set LOGFILE=\fileserveruptimelogs\%COMPUTERNAME%_uptime.log REM サーバー側で全ファイルをまとめて確認 dir \fileserveruptimelogs*_uptime.log
まとめ
| 目的 | 推奨方法 |
|---|---|
| 起動時刻を取得(Windows 10 以前) | wmic os get LastBootUpTime |
| 起動時刻を取得(Windows 11・将来対応) | powershell (Get-CimInstance Win32_OperatingSystem).LastBootUpTime |
| 稼働時間を計算 | PowerShell $uptime = (Get-Date) - $boot |
| ログファイルへの追記 | Add-Content -Encoding UTF8 または >> リダイレクト |
| CSV 形式で保存 | PowerShell で値を結合して CSV 追記 |
| 自動実行(ログオン時) | タスクスケジューラ schtasks /sc onlogon |
| 全エディションで使える起動時刻 | net stats workstation(OS 起動時刻と数秒ずれる) |
PowerShell との連携パターンの詳細は PowerShell をバッチファイルから呼び出す方法(連携パターンと使い分け) を、ログのサイズ管理・世代交代は バッチファイルのログローテーション実装ガイド(日付管理・自動削除・世代管理) を参照してください。ループ内での変数処理が必要な場合は setlocal enabledelayedexpansion 完全ガイド(FOR内変数・遅延展開) も合わせて確認してください。

