Powershell работа с журналами windows

Журнал событий Windows (Event Log) — это важный инструмент, который позволяет администратору отслеживать ошибки, предупреждения и другие информационные сообщения, которые регистрируются операционной системой, ее компонентами и различными программами. Для просмотра журнала событий Windows можно использовать графическую MMC оснастку Event Viewer (
eventvwr.msc
). В некоторых случаях для поиска информации в журналах событий и их анализа гораздо удобнее использовать PowerShell. В этой статье мы покажем, как получать информацию из журналов событий Windows с помощью командлета Get-WinEvent.

Содержание:

  • Получение логов Windows с помощью Get-WinEvent
  • Get-WinEvent: быстрый поиск в событиях Event Viewer с помощью FilterHashtable
  • Расширенный фильтры событий Get-WinEvent с помощью FilterXml
  • Получить логи Event Viewer с удаленных компьютеров

На данный момент в Windows доступны два командлета для доступа к событиям в Event Log: Get-EventLog и Get-WinEvent. В подавляющем большинстве случаев рекомендуем использовать именно Get-WinEvent, т.к. он более производителен, особенно в сценариях обработки большого количества событий с удаленных компьютеров. Командлет Get-EventLog является устаревшим и использовался для получения логов в более ранних версиях Windows. Кроме того, Get-EventLog не поддерживается в современных версиях PowerShell Core 7.x.

Получение логов Windows с помощью Get-WinEvent

Для использования команды Get-WinEvent нужно запустить PowerShell с правами администратора (при запуске Get-WinEvent от имени пользователя вы не сможете получить доступ к некоторым логам, например, к Security).

Для получения списка событий из определенного журнала, нужно указать его имя. В данном примере мы выведем последние 20 событий из журнала System:

Get-WinEvent -LogName Application -MaxEvents 20

Чаще всего вам нужно будет получать информацию из журналов System, Application, Security или Setup. Но вы можете указать и другие журналы. Полный список журналов событий в Windows можно получить с помощью команды:

Get-WinEvent -ListLog *

Get-WinEvent командлет PowerShell

Например, чтобы вывести события RDP подключений к компьютеру, нужно указать лог Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational:

Get-WinEvent -LogName Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational

Или получить логи SSH подключений к Windows из журнала OpenSSH/Operational:

Get-WinEvent -LogName OpenSSH/Operational

Можно выбрать события сразу из нескольких журналов. Например, чтобы получить информацию о ошибках и предупреждениях из журналов System и Application за последние 24 часа (сутки), можно использовать такой код:

$StartDate = (Get-Date) - (New-TimeSpan -Day 1)
Get-WinEvent Application,System | Where-Object {($_.LevelDisplayName -eq "Error" -or $_.LevelDisplayName -eq "Warning") -and ($_.TimeCreated -ge $StartDate )}

Get-WinEvent командлет для поиска событий в журнале Windows

Чтобы вывести только определенные поля событий, можно использовать Select-Object или Format-Table:

Get-WinEvent -LogName System | Format-Table Machinename, TimeCreated, Id, UserID

Get-WinEvent вывести определенные поля событий

Можно выполнить дополнительные преобразования с полученными данными. Например, в этом примере мы сразу преобразуем имя пользователя в SID:

Get-WinEvent -filterhash @{Logname = 'system'} |
Select-Object @{Name="Computername";Expression = {$_.machinename}},@{Name="UserName";Expression = {$_.UserId.translate([System.Security.Principal.NTAccount]).value}}, TimeCreated

Get-WinEvent: быстрый поиск в событиях Event Viewer с помощью FilterHashtable

Рассмотренный выше способ выбора определенных событий из журналов Event Viewer с помощью Select-Object прост для понимая, но выполняется крайне медленно. Это особенно заметно при выборке большого количества событий. В большинстве случаев для выборки событий нужно использовать фильтрацию на стороне службы Event Viewer с помощью параметра FilterHashtable.

Попробуем сформировать список ошибок и предупреждений за 30 дней с помощью Where-Object и FilterHashtable. Сравнима скорость выполнения этих двух команд PowerShell с помощью Measure-Command:

$StartDate = (Get-Date).AddDays(-30)

Проверим скорость выполнения команды с Where-Object:

(Measure-Command {Get-WinEvent Application,System | Where-Object {($_.LevelDisplayName -eq "Error" -or $_.LevelDisplayName -eq "Warning") -and ($_.TimeCreated -ge $StartDate )}}).TotalMilliseconds

Аналогичная команда с FilterHashtable:

(Measure-Command {Get-WinEvent -FilterHashtable @{LogName = 'System','Application'; Level =2,3; StartTime=$StartDate }})..TotalMilliseconds

В данном примере видно, что команда выборки событий через FilterHashtable выполняется в 30 раз быстрее, чем если бы обычный Where-Object (
2.5
сек vs
76
секунд).

Get-WinEvent FilterHashtable выполняется намного быстрее

Если вам нужно найти события по EventID, используйте следующую команду с FilterHashtable:

Get-WinEvent -FilterHashtable @{logname='System';id=1074}|ft TimeCreated,Id,Message

В параметре FilterHashtable можно использовать фильтры по следующим атрибутам событий:

  • LogName
  • ProviderName
  • Path
  • Keywords (для поиска успешных событий нужно использовать значение 9007199254740992 или для неуспешных попыток 4503599627370496)
  • ID
  • Level (1=FATAL, 2=ERROR, 3=Warning, 4=Information, 5=DEBUG, 6=TRACE, 0=Info)
  • StartTime
  • EndTime
  • UserID (SID пользователя)
  • Data

Пример поиска события за определенный промежуток времени:

Get-WinEvent -FilterHashTable @{LogName='System'; StartTime=(get-date).AddDays(-7); EndTime=(get-date).AddHours(-1); ID=1234}

Если нужно найти определенный текст в описании события, можно использовать такую команду:

Get-WinEvent -FilterHashtable @{logname='System'}|Where {$_.Message -like "*USB*"}

Get-WinEvent поиск текста в событиях

Расширенный фильтры событий Get-WinEvent с помощью FilterXml

Фильтры Get-WinEvent с параметром FilterHashtable являются несколько ограниченными. Если вам нужно использовать для выборки событий сложные запросы с множеством условий, нужно использовать параметр FilterXml, который позволяет сформировать запрос на выбор событий в Event Viewer с помощью XML запроса. Как и FilterHashtable, фильтры FilterXml выполняется на стороне сервера, поэтому результат вы получите довольно быстро.

Например, аналогичный запрос для получения последних ошибок из журнала System за последние 30 дней может выглядеть так:

$xmlQuery = @'
<QueryList>
<Query Id="0" Path="System">
<Select Path="System">*[System[(Level=2 or Level=3) and TimeCreated[timediff(@SystemTime) &lt;= 2592000000]]]</Select>
</Query>
</QueryList>
'@
Get-WinEvent -FilterXML $xmlQuery

Get-WinEvent -FilterXML

Для построения кода сложных XML запросов можно использовать графическую консоль Event Viewer:

  1. Запустите
    eventvwr.msc
    ;
  2. Найдите журнал для которого вы хотите создать и выберите Filter Current Log; Фильтр журнала событий Event Viewer
  3. Выберите необходимые параметры запроса в форме. В этом примере я хочу найти события с определенными EventID за последние 7 дней от определенного пользователя; формируем фильтр в Event Viewer
  4. Чтобы получить код XML запроса для параметра FilterXML, перейдите на вкладку XML и скопируйте полученный код (CTRL+A, CTRL+C); XML запрос в Event Viewer
  5. Если нужно, вы можете вручную отредактировать данный запрос.

Для экспорта списка событий в CSV файл нужно использовать командлет Export-CSV:

$Events= Get-WinEvent -FilterXML $xmlQuery
$events| Export-CSV "C:\ps\FilterSYSEvents.csv" -NoTypeInformation -Encoding UTF8

Получить логи Event Viewer с удаленных компьютеров

Для получения события с удаленного компьютер достаточно указать его имя в параметре -ComputerName:

$computer='msk-dc01'
Get-WinEvent -ComputerName $computer -FilterHashtable @{LogName="System"; StartTime=(get-date).AddHours(-24)} |   select Message,Id,TimeCreated

Можно опросить сразу несколько серверов/компьютеров и поискать на них определенные события. Список серверов можно получить из текстового файла:

$servers = Get-Content -Path C:\ps\servers.txt

Или из Active Directory:

$servers = (Get-ADComputer -Filter 'operatingsystem -like "*Windows server*" -and enabled -eq "true"').Name
foreach ($server in $servers) {
Get-WinEvent -ComputerName $server -MaxEvents 5 -FilterHashtable @{
LogName = 'System'; ID= 1234
} | Select-Object -Property ID, MachineName
}

Здесь есть другой пример для поиска событий блокировки учетной записи пользователя на всех контроллерах домена:

$Username = 'a.ivanov'
Get-ADDomainController -fi * | select -exp hostname | % {
$GweParams = @{
‘Computername’ = $_
‘LogName’ = ‘Security’
‘FilterXPath’ = "*[System[EventID=4740] and EventData[Data[@Name='TargetUserName']='$Username']]"
}
$Events = Get-WinEvent @GweParams
$Events | foreach {$_.Computer + " " +$_.Properties[1].value + ' ' + $_.TimeCreated}
}

Проникновение во внутреннюю сеть организации часто начинается с заражения рабочей станции сотрудника, например, с применением фишинговой рассылки. Анализ логов является одним из основных этапов проведения расследований инцидентов кибербезопасности.

В ОС существуют стандартные средства просмотра логов — Event Viewer, однако, при большом объёме информации требуется более масштабируемый и автоматизированный подход. Удобным решением является использование языка Powershell, что позволяет ощутимо упростить и увеличить скорость проведения анализа.

Основные команды Powershell для работы с логами: Get-EventLog (для работы с классическими журналами — Application, System, Security) и Get-WinEvent (для работы с любыми журналами). Список доступных журналов можно получить командой Get-WinEvent -ListLog. Вывести 10 последних записей журнала System позволяет команда Get-WinEvent –LogName ‘System’ –MaxEvents 10. Для более удобной фильтрации можно использовать хэш-таблицы, например, команда Get-WinEvent –FilterHashTable @{LogName=’Security’;ID=4740} выводит информацию о событиях журнала System с кодом 4740, генерация которых связана с блокировкой пользователя.

Для решения задачи получения удаленных входов на АРМ по RDP за последнюю неделю можно написать скрипт, сохранив его для удобства в отдельный файл.

$events = Get-WinEvent –FilterHashTable @{LogName=’Security’;StartTime=((get-date).Adddays(-7));ID=4624}
$result = $events | Where {$_.Properties[8].Values – eq 10} | foreach {
$event = $_
»$($event.TimeGenerated)$($event. Properties [5]) $($event. Properties [11])$($event. Properties [18])»
}
$result | out-file result.txt

В результате в файл выводится время события, имя пользователя, название рабочей станции и ip-адрес источника подключения.

Аналогичным образом можно выявлять в логах следы вредоносной активности, среди которых можно выделить:

  1. Перебор пользователей и групп (События 4798 и 4799)
  2. Создание локальной учётной записи и изменения в локальных группах (События 4720, 4722-4276, 4738, 4740, 4767, 4780, 4781,4794, 5376, 5377)
  3. Попытки входа с локальной учётной записью (События 4624)
  4. Подключение устройств Plug’n’Play (События 6416)

При необходимости сбора данных с нескольких АРМ целесообразно собирать логи удалённо. Используя опцию -ComputerName, можно получить логи с удалённого АРМ. Пример команд для сбора логов с нескольких компьютеров:

$comp_list = »comp1», »comp2», »comp3»
ForEach ($comp in $comp_list) {$comp; Get-EventLog –LogName Security –ComputerName $comp –After 01/10/21 | Where-Object {$_.EventID –eq »’6416»}}

В результате выполнения скрипт выведет события подключения устройств Plug’n’Play после 01/10/21 с АРМ, заданных в $comp_list.

В случае сложной инфраструктуры и большого числа рабочих мест организации необходимо централизованно собирать и хранить логи на сервере. Задача может быть реализована путём распространения на все компьютеры организации скрипта powershell, загружающего логи на сервер, с помощью MS SCCM, либо службы Active Directory.

Search code, repositories, users, issues, pull requests…

Provide feedback

Saved searches

Use saved searches to filter your results more quickly

Sign up

Пора поговорить про удобную работу с логами, тем более что в Windows есть масса неочевидных инструментов для этого. Например, Log Parser, который порой просто незаменим.

В статье не будет про серьезные вещи вроде Splunk и ELK (Elasticsearch + Logstash + Kibana). Сфокусируемся на простом и бесплатном.

Журналы и командная строка

До появления PowerShell можно было использовать такие утилиты cmd как find и findstr. Они вполне подходят для простой автоматизации. Например, когда мне понадобилось отлавливать ошибки в обмене 1С 7.7 я использовал в скриптах обмена простую команду:

findstr "Fail" *.log >> fail.txt

Она позволяла получить в файле fail.txt все ошибки обмена. Но если было нужно что-то большее, вроде получения информации о предшествующей ошибке, то приходилось создавать монструозные скрипты с циклами for или использовать сторонние утилиты. По счастью, с появлением PowerShell эти проблемы ушли в прошлое.

Основным инструментом для работы с текстовыми журналами является командлет Get-Content, предназначенный для отображения содержимого текстового файла. Например, для вывода журнала сервиса WSUS в консоль можно использовать команду:

Get-Content -Path 'C:\Program Files\Update Services\LogFiles\SoftwareDistribution.log' | Out-Host -Paging

Для вывода последних строк журнала существует параметр Tail, который в паре с параметром Wait позволит смотреть за журналом в режиме онлайн. Посмотрим, как идет обновление системы командой:

>Get-Content -Path "C:\Windows\WindowsUpdate.log" -Tail 5 -Wait


Смотрим за ходом обновления Windows.

Если же нам нужно отловить в журналах определенные события, то поможет командлет Select-String, который позволяет отобразить только строки, подходящие под маску поиска. Посмотрим на последние блокировки Windows Firewall:

Select-String -Path "C:\Windows\System32\LogFiles\Firewall\pfirewall.log" -Pattern 'Drop' | Select-Object -Last 20 | Format-Table Line


Смотрим, кто пытается пролезть на наш дедик.

При необходимости посмотреть в журнале строки перед и после нужной, можно использовать параметр Context. Например, для вывода трех строк после и трех строк перед ошибкой можно использовать команду:

Select-String 'C:\Windows\Cluster\Reports\Cluster.log' -Pattern ' err ' ‑Context 3

Оба полезных командлета можно объединить. Например, для вывода строк с 45 по 75 из netlogon.log поможет команда:

Get-Content 'C:\Windows\debug\netlogon.log' | Select-Object -First 30 -Skip 45

Журналы системы ведутся в формате .evtx, и для работы с ними существуют отдельные командлеты. Для работы с классическими журналами («Приложение», «Система», и т.д.) используется Get-Eventlog. Этот командлет удобен, но не позволяет работать с остальными журналами приложений и служб. Для работы с любыми журналами, включая классические, существует более универсальный вариант ― Get-WinEvent. Остановимся на нем подробнее.

Для получения списка доступных системных журналов можно выполнить следующую команду:

Get-WinEvent -ListLog *


Вывод доступных журналов и информации о них.

Для просмотра какого-то конкретного журнала нужно лишь добавить его имя. Для примера получим последние 20 записей из журнала System командой:

Get-WinEvent -LogName 'System' -MaxEvents 20


Последние записи в журнале System.

Для получения определенных событий удобнее всего использовать хэш-таблицы. Подробнее о работе с хэш-таблицами в PowerShell можно прочитать в материале Technet about_Hash_Tables.

Для примера получим все события из журнала System с кодом события 1 и 6013.

Get-WinEvent -FilterHashTable @{LogName='System';ID='1','6013'}

В случае если надо получить события определенного типа ― предупреждения или ошибки, ― нужно использовать фильтр по важности (Level). Возможны следующие значения:

  • 0 ― всегда записывать;
  • 1 ― критический;
  • 2 ― ошибка;
  • 3 ― предупреждение;
  • 4 ― информация;
  • 5 ― подробный (Verbose).

Собрать хэш-таблицу с несколькими значениями важности одной командой так просто не получится. Если мы хотим получить ошибки и предупреждения из системного журнала, можно воспользоваться дополнительной фильтрацией при помощи Where-Object:

Get-WinEvent -FilterHashtable @{LogName='system'} | Where-Object -FilterScript {($_.Level -eq 2) -or ($_.Level -eq 3)}


Ошибки и предупреждения журнала System.

Аналогичным образом можно собирать таблицу, фильтруя непосредственно по тексту события и по времени.

Подробнее почитать про работу обоих командлетов для работы с системными журналами можно в документации PowerShell:

  • Get-EventLog.
  • Get-WinEvent.

PowerShell ― механизм удобный и гибкий, но требует знания синтаксиса и для сложных условий и обработки большого количества файлов потребует написания полноценных скриптов. Но есть вариант обойтись всего-лишь SQL-запросами при помощи замечательного Log Parser.

Работаем с журналами посредством запросов SQL

Утилита Log Parser появилась на свет в начале «нулевых» и с тех пор успела обзавестись официальной графической оболочкой. Тем не менее актуальности своей она не потеряла и до сих пор остается для меня одним из самых любимых инструментов для анализа логов. Загрузить утилиту можно в Центре Загрузок Microsoft, графический интерфейс к ней ― в галерее Technet. О графическом интерфейсе чуть позже, начнем с самой утилиты.

О возможностях Log Parser уже рассказывалось в материале «LogParser — привычный взгляд на непривычные вещи», поэтому я начну с конкретных примеров.

Для начала разберемся с текстовыми файлами ― например, получим список подключений по RDP, заблокированных нашим фаерволом. Для получения такой информации вполне подойдет следующий SQL-запрос:

SELECT 
 extract_token(text, 0, ' ') as date, 
 extract_token(text, 1, ' ') as time,
 extract_token(text, 2, ' ') as action, 
 extract_token(text, 4, ' ') as src-ip,  
 extract_token(text, 7, ' ') as port 
FROM 'C:\Windows\System32\LogFiles\Firewall\pfirewall.log' 
WHERE action='DROP' AND port='3389'
ORDER BY date,time DESC

Посмотрим на результат:


Смотрим журнал Windows Firewall.

Разумеется, с полученной таблицей можно делать все что угодно ― сортировать, группировать. Насколько хватит фантазии и знания SQL.

Log Parser также прекрасно работает с множеством других источников. Например, посмотрим откуда пользователи подключались к нашему серверу по RDP.

Работать будем с журналом TerminalServices-LocalSessionManager\Operational.

Не со всеми журналами Log Parser работает просто так ― к некоторым он не может получить доступ. В нашем случае просто скопируем журнал из %SystemRoot%\System32\Winevt\Logs\Microsoft-Windows-TerminalServices-LocalSessionManager%4Operational.evtx в %temp%\test.evtx.

Данные будем получать таким запросом:

SELECT
 timegenerated as Date, 
 extract_token(strings, 0, '|') as user,
 extract_token(strings, 2, '|') as sourceip 
FROM '%temp%\test.evtx'
WHERE EventID = 21
ORDER BY Date DESC


Смотрим, кто и когда подключался к нашему серверу терминалов.

Особенно удобно использовать Log Parser для работы с большим количеством файлов журналов ― например, в IIS или Exchange. Благодаря возможностям SQL можно получать самую разную аналитическую информацию, вплоть до статистики версий IOS и Android, которые подключаются к вашему серверу.

В качестве примера посмотрим статистику количества писем по дням таким запросом:

SELECT
 TO_LOCALTIME(TO_TIMESTAMP(EXTRACT_PREFIX(TO_STRING([#Fields: date-time]),0,'T'), 'yyyy-MM-dd')) AS Date,
 COUNT(*) AS [Daily Email Traffic] 
FROM 'C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Logs\MessageTracking\*.LOG'
WHERE (event-id='RECEIVE') GROUP BY Date ORDER BY Date ASC

Если в системе установлены Office Web Components, загрузить которые можно в Центре загрузки Microsoft, то на выходе можно получить красивую диаграмму.


Выполняем запрос и открываем получившуюся картинку…


Любуемся результатом.

Следует отметить, что после установки Log Parser в системе регистрируется COM-компонент MSUtil.LogQuery. Он позволяет делать запросы к движку утилиты не только через вызов LogParser.exe, но и при помощи любого другого привычного языка. В качестве примера приведу простой скрипт PowerShell, который выведет 20 наиболее объемных файлов на диске С.

$LogQuery = New-Object -ComObject "MSUtil.LogQuery"
$InputFormat = New-Object -ComObject "MSUtil.LogQuery.FileSystemInputFormat"
$InputFormat.Recurse = -1
$OutputFormat = New-Object -ComObject "MSUtil.LogQuery.CSVOutputFormat"
$SQLQuery = "SELECT Top 20 Path, Size INTO '%temp%\output.csv' FROM 'C:\*.*' ORDER BY Size DESC"
$LogQuery.ExecuteBatch($SQLQuery, $InputFormat, $OutputFormat)
$CSV = Import-Csv  $env:TEMP'\output.csv'
$CSV | fl 
Remove-Item $env:TEMP'\output.csv'
$LogQuery=$null
$InputFormat=$null
$OutputFormat=$null

Ознакомиться с документацией о работе компонента можно в материале Log Parser COM API Overview на портале SystemManager.ru.

Благодаря этой возможности для облегчения работы существует несколько утилит, представляющих из себя графическую оболочку для Log Parser. Платные рассматривать не буду, а вот бесплатную Log Parser Studio покажу.


Интерфейс Log Parser Studio.

Основной особенностью здесь является библиотека, которая позволяет держать все запросы в одном месте, без россыпи по папкам. Также сходу представлено множество готовых примеров, которые помогут разобраться с запросами.

Вторая особенность ― возможность экспорта запроса в скрипт PowerShell.

В качестве примера посмотрим, как будет работать выборка ящиков, отправляющих больше всего писем:


Выборка наиболее активных ящиков.

При этом можно выбрать куда больше типов журналов. Например, в «чистом» Log Parser существуют ограничения по типам входных данных, и отдельного типа для Exchange нет ― нужно самостоятельно вводить описания полей и пропуск заголовков. В Log Parser Studio нужные форматы уже готовы к использованию.

Помимо Log Parser, с логами можно работать и при помощи возможностей MS Excel, которые упоминались в материале «Excel вместо PowerShell». Но максимального удобства можно достичь, подготавливая первичный материал при помощи Log Parser с последующей обработкой его через Power Query в Excel.

Приходилось ли вам использовать какие-либо инструменты для перелопачивания логов? Поделитесь в комментариях.

Today, I’m going to show you how you can use Windows PowerShell to quickly and easily find the Windows event log entries that you need to see right now. By the end of this article, you’ll understand how to write event log queries that pull selected events from local and/or remote Windows computers.

Contents

  1. Understanding Get-EventLog
  2. Where’s the Event ID?
  3. More event log search tips
  4. Remote event logs
  5. The Get-WinEvent cmdlet

Recall that we use good ol’ Event Viewer (eventvwr.msc) to read event messages in a graphical environment.

Our old friend the Windows Event Viewer

Our old friend the Windows Event Viewer

Ever since Windows Vista, we’ve had far more than the handful of “classic” Windows event logs. Let’s learn how to wrangle all those thousands of messages programmatically by using Windows PowerShell.

Understanding Get-EventLog

The Get-EventLog cmdlet has two parameter sets, as you can see in the partial help output below:

PS C:\> Get-Help Get-EventLog

Synopsis
     Gets the events in an event log, or a list of the event logs, on the local or remote computers.

Syntax
     Get-EventLog [-LogName] <String> [[-InstanceId] <Int64[]>] [-After <DateTime>] [-AsBaseObject ] [-Before <DateTime>] [-ComputerName <String[]>] [-EntryType <String[]>] [-Index <Int32[]>] [-Message <String>] [-Newest <Int32>] [-Source <String[]>] [-UserName <String[]>] [<CommonParameters>]

     Get-EventLog [-AsString ] [-ComputerName <String[]>] [-List ] [<CommonParameters>]

Basically, we use the first parameter set to interrogate event log contents. We invoke the second parameter set to view “meta” information about our event logs, like so:

PS C:\> Get-EventLog -List | Sort-Object -Property Entries -Descending

   Max(K) Retain OverflowAction        Entries Log
   ------ ------ --------------        ------- ---
   20,480      0 OverwriteAsNeeded       2,928 Security
   20,480      0 OverwriteAsNeeded       1,449 Application
   20,480      0 OverwriteAsNeeded       1,421 System
   15,360      0 OverwriteAsNeeded         126 Windows PowerShell
      512      0 OverwriteAsNeeded           4 ThinPrint Diagnostics
      128      0 OverwriteAsNeeded           0 OAlerts
   20,480      0 OverwriteAsNeeded           0 HardwareEvents
   20,480      0 OverwriteAsNeeded           0 Key Management Service
      512      7 OverwriteOlder              0 Internet Explorer

Now let’s use the first (most common) parameter set to see the latest three entries from my Windows 8.1 computer’s System log:

Get-EventLog -LogName System | Select-Object -First 3

    Index Time          EntryType   Source                 InstanceID Message
    ----- ----          ---------   ------                 ---------- -------
     1421 Apr 15 20:05  Information Service Control M...   1073748864 The sta...
     1420 Apr 15 19:05  Information Microsoft-Windows...           17 Install...
     1419 Apr 15 19:05  Information Microsoft-Windows...           17 Install...

By the way, we can do the same thing from within the Get-EventLog cmdlet:

Get-EventLog –LogName System –Newest 3

It pays to read the documentation!

In any event, I find that the event log data is so dense that the default Format-Table output truncates the most important stuff! Let’s view the most recent System log entry in list view instead:

PS C:\> Get-EventLog -LogName System -Index 1421 | Format-List

Index              : 1421
EntryType          : Information
InstanceId         : 1073748864
Message            : The start type of the Background Intelligent Transfer
                      Service service was changed from auto start to demand
                      start.
Category           : (0)
CategoryNumber     : 0
ReplacementStrings : {Background Intelligent Transfer Service, auto start,
                      demand start, BITS}
Source             : Service Control Manager
TimeGenerated      : 4/15/2015 8:05:11 PM
TimeWritten        : 4/15/2015 8:05:11 PM
UserName           : NT AUTHORITY\SYSTEM

Much better, but still verbose. We’ll whittle away at this problem as we proceed through the rest of this tutorial.

Where’s the Event ID?

In my experience as a Windows systems administrator, I use the Event ID as the most useful “handle” for investigating event log entries. Sadly, the PowerShell team chose not to include EventID as a default property. We can fix that, though.

Let’s view the full property list for that newest System log entry we used earlier:

PS C:\> Get-EventLog -LogName System -Index 1421 | Get-Member -MemberType Properties


    TypeName: System.Diagnostics.EventLogEntry#System/Service ControlManager/1073748864

Name               MemberType     Definition
----               ----------     ----------
Category           Property       string Category {get;}
CategoryNumber     Property       int16 CategoryNumber {get;}
Container          Property       System.ComponentModel.IContainer Container...
Data               Property       byte[] Data {get;}
EntryType          Property       System.Diagnostics.EventLogEntryType Entry...
Index              Property       int Index {get;}
InstanceId         Property       long InstanceId {get;}
MachineName        Property       string MachineName {get;}
Message            Property       string Message {get;}
ReplacementStrings Property       string[] ReplacementStrings {get;}
Site               Property       System.ComponentModel.ISite Site {get;set;}
Source             Property       string Source {get;}
TimeGenerated      Property       datetime TimeGenerated {get;}
TimeWritten        Property       datetime TimeWritten {get;}
UserName           Property       string UserName {get;}
EventID            ScriptProperty System.Object EventID {get=$this.get_Event...

A-ha! As it happens, EventID isn’t even a native .NET property. Instead, it’s a ScriptProperty, which means that this synthetic member relies on a direct call to the .NET Framework. Let’s look deeper at this situation:

PS C:\> Get-EventLog -LogName System -Index 1421 | Get-Member -Name EventID | Format-List

TypeName   : System.Diagnostics.EventLogEntry#System/Service Control
              Manager/1073748864
Name       : EventID
MemberType : ScriptProperty
Definition : System.Object EventID {get=$this.get_EventID() -band 0xFFFF;}

Alrighty then—the ScriptProperty pulls the EventID directly from the .NET Framework. I wonder why the PowerShell team exposed EventID this way. Inquiring minds want to know!

In any event, we can recast our Get-EventLog statement to show us the EventID column with no muss, fuss, or greasy aftertaste:

PS C:\> Get-EventLog -LogName System -Newest 3 | Sort-Object -Property TimeGenerated -Descending | Select-Object -Property TimeGenerated, Source, EventID, Message | Format-Table -AutoSize

TimeGenerated        Source                                EventID Message
-------------        ------                                ------- -------
4/15/2015 8:05:11 PM Service Control Manager                  7040 The start...
4/15/2015 7:05:45 PM Microsoft-Windows-WindowsUpdateClient      17 Installat...
4/15/2015 7:05:40 PM Microsoft-Windows-WindowsUpdateClient      17 Installat...

Of course, if we know the Event ID we’re looking for, we can include a Where-Object expression:

PS C:\> Get-EventLog -LogName System | Where-Object { $_.EventID -eq "17" } | Sort-Object -Property TimeGenerated -Descending

    Index Time          EntryType   Source                 InstanceID Message
    ----- ----          ---------   ------                 ---------- -------
     1424 Apr 16 00:21  Information Microsoft-Windows...           17 Install...
     1420 Apr 15 19:05  Information Microsoft-Windows...           17 Install...
     1417 Apr 15 19:05  Information Microsoft-Windows...           17 Install...
     1418 Apr 15 19:05  Information Microsoft-Windows...           17 Install...

More event log search tips

If you’re a busy systems administrator like I am, your event log scans occur either when you know there’s a problem or you at least suspect there’s one. To that point, we can pass the –EntryType parameter to filter our results based on, well, the entry type:

Get-EventLog –LogName System –EntryType Error

You should know that Get-EventLog can fetch log entries not only from the “classic” logs but also from the plethora of Application and Services logs. Let’s run a search of the Windows PowerShell log to find all entries that include the string “stopped”:

Get-EventLog –LogName "Windows PowerShell" –Message "*stopped*"

Don’t forget about PowerShell tab completion. In the previous example, you can press TAB after typing a few characters of “Windows PowerShell” to let PowerShell complete the log name for you.

We can leverage Group-Object to perform aggregations. For instance, let’s group events from the System log by EventID count:

Get-EventLog –LogName System | Group-Object –Property EventID | Sort-Object –Property Count -Descending

Time is of the essence, as it were. We can use the –Before and –After parameters of Get-EventLog to do time/date-based queries. The following query picks up all System log errors in the past seven days:

Get-EventLog –LogName System –EntryType Error –After (Get-Date).AddDays(-7)

We can do a date range as well. Let’s run the previous query, this time focusing it on a particular date:

Get-EventLog –LogName System –After 04/14/2015 –Before 04/15/2015

Note that PowerShell uses the American date format of Month/Day/Year instead of the European Day/Month/Year.

Thus far in this tutorial, we’ve searched only one log at a time. What if we need to aggregate, say, error messages across the entire Windows event log platform?

Because Get-EventLog hits only one log at a time, we’ll need to tap into Windows Management Instrumentation (WMI) to get the job done (hat tip: PowerShell.com). Actually, we’ll use the newer Get-CimInstance instead of the shopworn Get-WmiObject for this task.

The following one-liner fetches the first 100 error events from the System and Application log files of the local host:

PS C:\> Get-CimInstance -ClassName Win32_NTLogEvent -Filter 'Type="Error" AND (LogFile="System" OR LogFile="Application")' | Select -First 100 -Property TimeGenerated, Logfile, EventCode, Message

TimeGenerated       Logfile                       EventCode Message
-------------       -------                       --------- -------
4/7/2015 1:46:41 PM Application                        2006 There was an err...
3/19/2015 1:05:5... Application                          24 Event provider P...
3/19/2015 1:05:5... Application                          24 Event provider  ...
4/7/2015 1:47:04 PM System                            10010 The server {4545...
4/7/2015 2:03:39 AM System                            10010 The server {BF6C...
4/7/2015 2:03:12 AM System                            10010 The server {1B1F...

Remote event logs

Everything we’ve learned thus far concerning Get-EventLog applies 100 percent to Windows PowerShell remoting. We’ll use Invoke-Command, which employs “true” Windows Remote Management (WinRM)-based remoting and parallel execution, to query the Security log of multiple computers:

PS C:\> Invoke-Command -ComputerName dc1,vpnclient1,lync1 -ScriptBlock { Get-EventLog -LogName Security -Newest 1 | Select-Object -Property PSComputerName, TimeGenerated, EventID }

TimeGenerated  : 4/16/2015 8:58:30 AM
EventID        : 4624
PSComputerName : lync1
RunspaceId     : 6896e2be-aa1e-4af9-911d-a959e88121b6

TimeGenerated  : 4/16/2015 8:58:30 AM
EventID        : 4624
PSComputerName : vpnclient1
RunspaceId     : 5b44b5cf-4e84-4ea9-8902-083618f09af7

TimeGenerated  : 4/16/2015 8:58:30 AM
EventID        : 4624
PSComputerName : dc1
RunspaceId     : 5714e2f6-297b-4442-b76b-9d1ed3cd042a

One (of many) nice things about Invoke-Command over, say, the –ComputerName parameter of Get-Wmiobject is that Invoke-Command includes the PSComputer object in the output. I think you’ll agree that it’s nice to see which remote host each event log entry comes from!

The Get-WinEvent cmdlet

Many Windows administrators are completely unaware that we have Get-WinEvent in addition to Get-EventLog. What are the differences? Two come to my mind:

  • Get-WinEvent gives you much wider and deeper reach into the event logs. It can access log providers directly as well as tap into Windows event tracing logs. That said, it’s easier to delve into the content of classic event log entries with Get-EventLog.
  • For remoting, Get-WinEvent uses the built-in Windows event log remoting technology instead of PowerShell remoting. Thus, you’ll find that remote log queries run faster with Get-WinEvent than with Get-EventLog.

To see what I’m talking about in terms of Get-WinEvent’s reach, run each of the following commands and note the output differences:

Get-EventLog -List
Get-WinEvent –ListLog *

The “word on the street” from Windows PowerShell MVPs I’ve spoken with is that Microsoft will eventually deprecate Get-EventLog in favor of Get-WinEvent. Evidence for this position is that, for instance, some of the newer logs such as Desired State Configuration (DSC) are of the “new school” variety and are accessible only with Get-WinEvent.

Let’s close with a couple of quick Get-WinEvent examples. First, we’ll gather the most recent 10 events from the Application log:

Get-WinEvent –LogName Application –MaxEvents 10

Thanks to Richard Siddaway’s fine example, we’ll now pull the most recent 500 error messages from the Application log:

Get-WinEvent -Logname Application -MaxEvents 500 |Where-Object { $_.LevelDisplayName -eq "Error" } | Format-Table –Property Id, LevelDisplayName, Message -AutoSize

I hope you found this article helpful. Thanks for reading, and happy PowerShelling!

  • Powerpoint download for windows 10 free
  • Powershell отключить обновление windows 10
  • Powerpoint 365 скачать бесплатно для windows 10
  • Powershell module activedirectory windows 10
  • Powershell messagebox system windows forms