
Журнал событий Windows – это важный инструмент для администраторов, позволяющий отслеживать ошибки, предупреждения и другие информационные сообщения, которые регистрируются операционной системой, ее компонентами или программами. Вы можете использовать графическую оснастку MMC Event Viewer (eventvwr.msc
) для просмотра журнала событий Windows. В некоторых случаях гораздо удобнее использовать PowerShell для разбора и анализа информации из журналов событий. В этой статье вы узнаете, как использовать Get-WinEvent Команда для получения информации из журналов событий Windows.
Get-WinEvent: Поиск в журналах событий с помощью PowerShell
Чтобы использовать команду Get-WinEvent, необходимо запустить PowerShell от имени администратора. Если вы попытаетесь запустить Get-WinEvent от имени пользователя, не являющегося администратором, вы не сможете получить доступ к некоторым журналам, включая журналы безопасности.
Чтобы получить список событий из определенного журнала, необходимо указать его имя. Например, следующая команда выводит список последних 20 событий из журнала System:
Get-WinEvent -LogName Application -MaxEvents 20
Наиболее часто запрашиваются журналы System, Application, Security или Setup. Можно указать и другие имена журналов. Полный список журналов событий в Windows можно получить с помощью команды:
Get-WinEvent -ListLog *
Например, чтобы просмотреть историю RDP-соединений на компьютере, необходимо указать параметр Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational
log:
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 )}
Вы можете использовать функцию Select-Object или Format-Table, чтобы отобразить только определенные поля события:
Get-WinEvent -LogName System | Format-Table Machinename, TimeCreated, Id, UserID
Данные, полученные из журнала событий, можно обрабатывать и дальше. В этом примере мы сразу преобразуем имя пользователя в SID:
Get-WinEvent -filterhash @{Logname="system"} |
Select-Object @{Name="Computername";Expression = {$_.machinename}},@{Name="UserName";Expression = {$_.UserId.translate([System.Security.Principal.NTAccount]).value}}, TimeCreated
Быстрый поиск событий с помощью опции FilterHashtable
Приведенный выше метод фильтрации определенных событий из журналов Event Viewer с помощью Where-Object может быть прост для понимания, но он чрезвычайно медленный, особенно если вы хотите выполнить поиск по большому количеству событий. В большинстве случаев лучше использовать фильтрацию на стороне сервера Event Viewer с помощью опции FilterHashtable вариант.
Теперь попробуем сгенерировать список ошибок и предупреждений за 30-дневный период с помощью Where-Object и FilterHashtable. Для этого мы воспользуемся Measure-Command
для сравнения времени выполнения этих двух команд PowerShell:
$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
секунды против 76
сек).
Если вам нужно найти события по EventID, используйте следующую команду с параметром FilterHashtable:
Get-WinEvent -FilterHashtable @{logname="System";id=1074}|ft TimeCreated,Id,Message
Аргумент FilterHashtable позволяет фильтровать по следующим атрибутам событий:
- LogName
- ProviderName
- Путь
- Ключевые слова (использовать 9007199254740992 для поиска успешных событий и 4503599627370496 для неудачных)
- ID
- Уровень (1=FATAL, 2=ERROR, 3=Warning, 4=Information, 5=DEBUG, 6=TRACE, 0=Info)
- StartTime
- EndTime
- UserID (SID пользователя)
- Данные
Вот пример поиска события за определенный период времени:
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 с помощью FilterXml
Фильтры Get-WinEvent с опцией FilterHashtable имеют некоторые ограничения. Если вам нужно использовать сложные запросы с большим количеством критериев для отбора событий, вам нужно использовать опцию FilterXml флаг, который позволяет сделать выборку с помощью XML-запроса. Как и FilterHashtable, фильтры FilterXml работают на стороне сервера. Это означает, что вы получите результат довольно быстро.
Например, вот еще один способ получить последние ошибки из системного журнала за последние 30 дней:
$xmlQuery = @'
<QueryList>
<Query Id="0" Path="System">
<Select Path="System">*[System[(Level=2 or Level=3) and TimeCreated[timediff(@SystemTime) <= 2592000000]]]</Select>
</Query>
</QueryList>
'@
Get-WinEvent -FilterXML $xmlQuery
Чтобы сгенерировать сложный XML-код запроса, можно воспользоваться графической консолью Event Viewer:
- Выполните команду
eventvwr.msc
; - Найдите журнал, для которого вы хотите создать запрос, и нажмите кнопку Фильтр текущего журнала;
- Выберите необходимые параметры запроса в форме фильтра. В этом примере я хочу найти события с определенными идентификаторами EventID за последние 7 дней для конкретного пользователя;
- Чтобы получить код XML-запроса, перейдите на вкладку XML и скопируйте код XPath (
CTRL+A
,CTRL+C
); - При необходимости вы можете отредактировать этот запрос вручную.
Чтобы экспортировать список событий в CSV-файл, используйте команду Export-CSV:
$Events= Get-WinEvent -FilterXML $xmlQuery
$events| Export-CSV "C:\ps\FilterSYSEvents.csv" -NoTypeInformation -Encoding UTF8
Получение журналов событий с удаленных компьютеров
Чтобы получить события с удаленного компьютера, просто укажите его имя в поле -ComputerName параметр:
$computer="mun-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.muller"
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}
}