Powershell: как извлечь время из поля сообщений в Eventlog?

Я пытаюсь получить неожиданное время выключения компьютеров Windows Sever 2008 через Get-EventLog в Powershell. Я могу приблизиться, ища события с EventID из 6008 и выбрав только message, но мне нужно проанализировать поле, чтобы получить время, когда оно произошло (а не время, когда событие сработало).

Я пытался использовать replacementstrings[x] но я не могу найти, как указать поле для использования (messages) и не могу получить результат.

get-eventlog -LogName System -ComputerName svr-name | Where-Object {$_.EventID -eq 6008 -AND $_.timegenerated -gt (get-date).adddays(-30)}| select message

Производит это:

Message
-------
The previous system shutdown at 3:35:32 AM on ‎7/‎29/‎2014 was unexpected.
The previous system shutdown at 3:40:06 PM on ‎7/‎10/‎2014 was unexpected.`

3 ответа

Решение

Извлечение всех событий с удаленного хоста и их фильтрация на локальном компьютере обычно не слишком эффективны, потому что таким образом вы передаете тонны несвязанных событий по сети, просто чтобы выбросить их. Get-EventLog имеет параметры для фильтрации сообщений по идентификатору события или до / после заданной отметки времени в источнике, поэтому лучше использовать их для предварительного выбора сообщений, которые вам действительно интересны. Отметку времени сбоя можно извлечь из Message поле с регулярным выражением и анализируется в DateTime значение через ParseExact():

$log     = 'System'
$server  = 'svr-name'
$id      = [uint64]"0x80000000" + 6008
$date    = (Get-Date).AddDays(-30)

$fmt     = 'h:mm:ss tt on M\/d\/yyyy'
$culture = [Globalization.CultureInfo]::InvariantCulture

Get-EventLog -LogName $log -ComputerName $server -InstanceId $id -After $date | ? {
  $_.Message -match 'at (\d+:\d+:\d+ [ap]m on \d+/\d+/\d+) was unexpected'
} | select MachineName, TimeGenerated,
           @{n='Crashtime';e={[DateTime]::ParseExact($matches[1], $fmt, $culture)}}

Конвейер создает список объектов со свойствами MachineName, TimeGenerated а также Crashtime (последний является расчетным свойством). Если вы собираете выходные данные конвейера в переменную (например, $evt) вы можете получить доступ к Crashtime свойство третьего объекта, как это:

$evt = .\script.ps1
$evt[2].Crashtime

Используя регулярные выражения, вы можете вытащить его как таковой.

$Messages = (get-eventlog -LogName System -ComputerName svr-name | Where-Object {$_.EventID -eq 6008 -AND $_.timegenerated -gt (get-date).adddays(-30) }| select message)
$Messages | ForEach-Object { 
    $Matched = $_.Message -match "([0-9]{1,2}:.*[0-9]{4})"
    if ($Matched) {
        Write-Output "System rebooted at $($Matches[1])" 
    }
}

Возможно, есть лучший способ, но я не знаю, что:)

Пример вывода из моей системы

System rebooted at 4:34:30 PM on ‎4/‎20/‎2014
System rebooted at 1:48:38 PM on ‎1/‎21/‎2014
System rebooted at 1:37:12 PM on ‎1/‎21/‎2014
System rebooted at 1:22:01 PM on ‎1/‎21/‎2014
System rebooted at 4:41:21 PM on ‎11/‎22/‎2013

Более легко

get-eventlog system  | where-object {$_.EventID -eq  "6008"} | fl
Другие вопросы по тегам