2012年5月23日水曜日

◆PCの起動終了時刻を表示する

以前PowerShell: ◆最近何時に帰ったか調べる(shutdownイベントを拾う)で終了時刻を表示するのはやったことがあるのだが、ふとしたところで起動時間も一緒に表示したいと要望されて作ってみた。

終了時刻が表示できているので起動時刻を表示するのも特に問題は無い。

それぞれを別に表示するのであれば「イベントID」を変えて実行するだけ。

しかし、通常は「起動」と「終了」を同一行に表示させたいというのが人情だろう。
まぁそれも特に問題は無いだろうと思ったのだが意外と簡単な方法が浮かばない。

片方に「日付と起動時間」、もう片方に「日付と終了時間」があり、これを一行に纏める。
数十年前の遠い昔によくやったバッチ処理のような問題だ。
実際にこれがバッチ処理なら何も迷うことは無い典型的なパターン。
それぞれを日付でソートしてマッチングしてくっつけながら出力していけば良い。

しかし、PowerShellではどうすればスマートなんでしょうね・・・。

とりあえず私は「Group-Object」を使ってグルーピングしてやるケースが多い。
こんな感じ。

001
002
003
004
005
006
007
008
009
010
011
012
013

$startID = 2147489653;$endID = 2147489654
Get-EventLog system -InstanceId $startID,$endID
 `
 
-After ((Get-Date).AddMonths(-1)) | select timewritten,InstanceId |
 
   
group {($_.TimeWritten).ToString("yyyyMMdd")} | sort name | %
{
     
$obj = New-Object PsObject -Property @{日付=$_.name;起動="";終了=""
}
     
$_ | select -ExpandProperty group | %
{
       
if($_.InstanceId -eq $startID
){
     
$obj.起動 = $_.TimeWritten.ToString("HH:mm:ss"
)}
       
if($_.InstanceId -eq $endID
){
     
$obj.終了 = $_.TimeWritten.ToString("HH:mm:ss"
)}
      }
     
$obj | select 日付,起動,終了
  }
<!--End

一日に複数回起動することを考慮しなければこれで良いのだが、通常はPCを再起動することもあるだろう。
その場合は、起動のイベントと終了のイベントをそれぞれ再度グルーピングして最も早いものと最も遅いものを抽出する必要がある。

ちょっとネストが深くなって気乗りがしない・・・。
処理時間がシビアな場合は仕方がないがもう少し簡単に行きたい。

というわけでPowerShell: ◆最近何時に帰ったか調べる(shutdownイベントを拾う)と同じロジックで起動時間を取得しそれぞれをくっつけることにした。

</TBOD
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028

$startID = 2147489653;$endID = 2147489654
$log = Get-EventLog system -InstanceId $startID,$endID
 `
 
-After ((Get-Date).AddMonths(-1))
$StartObj = $log | ?{$_.InstanceId -eq $startID} | select timewritten |
 
 
sort timewritten | group {($_.TimeWritten).day} | %
{
   
$startTime = (@($_.group)[0]).
TimeWritten
   
New-Object PsObject -Property @{日付=$startTime.ToString("yyyyMMdd"
)
                  起動
=$startTime.ToString("HH:mm:ss"
)}
} 

$EndObj = $log | ?{$_.InstanceId -eq $endID} | select timewritten |
  sort timewritten | group {($_.TimeWritten).day} | %
{
   
$endTime = (@($_.group)[-1]).
TimeWritten 
   
New-Object PsObject -Property @{日付=$endTime.ToString("yyyyMMdd"
)
                  終了
=$endTime.ToString("HH:mm:ss"
)}
}


$list = $StartObj+$EndObj | sort 日付 | group 日付 | %
{
 
$outObj = 1 | select 日付,起動,終了
  $outObj.日付 = $_.
name

 
$_ | select -ExpandProperty group | %
{
   
if($_.起動){$outObj.起動 = $_.
起動}
   
if($_.終了){$outObj.終了 = $_.
終了}
  }
 
$outObj
}
$list | ft -AutoSize
Read-Host please Enter

Shutdownイベントを拾うのが実質1行で済んでいたのと比べるとなんか大きくなりすぎている感じはするが・・・。
image

あれ、今日と1か月前と日付がぶつかっているのかな。
5行目と11行目は「Day」プロパティではなく「ToShortDateString()」メソッドですかね。

0 件のコメント:

コメントを投稿