Get-WinEvent: читаємо Event Log у PowerShell — правильно і швидко
- PowerShell 5.1 або новіший.
Get-WinEventє у Windows Vista/Server 2008 і новіше. - Для читання Security-логу потрібні права адміна. Для System/Application — звичайних прав зазвичай досить.
- Для віддаленої перевірки —
-ComputerName+ відкриті WMI/WinRM порти.
Get-WinEvent vs Get-EventLog vs wevtutil
Get-WinEvent— сучасний, швидкий, бачить усі Application-and-Services Logs (саме там цікаве — GroupPolicy/Operational, PrintService, WMI, SChannel). Стандартний вибір.Get-EventLog— легасі, бачить тільки класичні логи (System/Application/Security). Deprecated у PowerShell 7+.wevtutil qe— cmd-утиліта, працює без PowerShell, швидка, XML-вивід. Корисна для крос-платформених скриптів і коли PowerShell недоступний.
Синтаксис FilterHashtable — ключ до швидкості
Найчастіший anti-pattern початківців:
Get-WinEvent -LogName System | Where-Object {$_.Id -eq 41}
Це читає весь System-лог у пам'ять, потім фільтрує. На сервері з великим логом — 30-60 секунд і гігабайти RAM. Правильно:
Get-WinEvent -FilterHashtable @{LogName='System'; Id=41}
Тут фільтр передається в ядро Event Log API, результат повертається вже відфільтрований — 1-2 секунди на тому ж сервері.
Ключі FilterHashtable:
LogName— назва логу (System, Application, Security, або будь-який з повного шляху).ProviderName— джерело події (наприкладMicrosoft-Windows-Kernel-Power).Id— Event ID (одне число або масив).Level— рівень: 1=Critical, 2=Error, 3=Warning, 4=Information, 5=Verbose.StartTime/EndTime— часовий діапазон.UserID— SID користувача (для Security-логу).Data— рядок для повнотекстового пошуку всередині EventData.
Сценарій 1. Чому сервер перезавантажився
Задача: вчора вночі сервер перезавантажився. Треба зрозуміти — планове оновлення, BSOD, чи адмін сам?
Get-WinEvent -FilterHashtable @{LogName='System'; Id=41,1074,6006,6008} -MaxEvents 10 | Select TimeCreated, Id, Message
Що показують ці події:
- 41 (Kernel-Power) — «система була перезавантажена некоректно». BSOD, power loss, hard reset.
- 1074 (User32) — «користувач або процес ініціював reboot/shutdown». Видно хто і чому (Windows Update, admin, application).
- 6006 — Event Log зупинився (нормальне відключення).
- 6008 — попереднє завершення було некоректним (неплановий reboot).
За цими 4 подіями ви 90% випадків одразу розумієте природу reboot.
Сценарій 2. Account lockout forensics
Задача: користувач скаржиться, що «мене заблокувало». Треба знайти, звідки йшли невдалі логіни.
На PDC (де реєструються всі lockout) у Security-лог:
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4740} -MaxEvents 20 |
ForEach-Object {
[PSCustomObject]@{
Time = $_.TimeCreated
User = $_.Properties[0].Value
CallerComputer = $_.Properties[1].Value
}
}
Event 4740 — «A user account was locked out». У Properties[1] — ім'я комп'ютера, з якого прийшов останній невдалий логін (і який спричинив lockout).
Далі на цьому комп'ютері:
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625; StartTime=(Get-Date).AddMinutes(-30)} |
Select TimeCreated, @{n='AccountName';e={$_.Properties[5].Value}}, @{n='Source';e={$_.Properties[19].Value}}
Event 4625 — «Failed logon». Звідси видно причину блокування: збережений пароль у scheduled task, RDP-сесія з застарілим паролем, VPN-клієнт, тощо.
Сценарій 3. Падіння застосунку — шукаємо крашдампи
Задача: Outlook падає у випадкових користувачів. Треба зібрати статистику по падіннях за тиждень.
Get-WinEvent -FilterHashtable @{
LogName='Application';
ProviderName='Application Error';
StartTime=(Get-Date).AddDays(-7)
} | Group-Object {($_.Properties[0].Value)} | Sort Count -Descending | Select Count, Name
Групуємо за назвою exe — побачите, яка програма крашиться найчастіше. Якщо Outlook у топі — далі дивимось конкретні повідомлення:
Get-WinEvent -FilterHashtable @{
LogName='Application';
ProviderName='Application Error';
StartTime=(Get-Date).AddDays(-1)
} | Where-Object {$_.Properties[0].Value -eq 'OUTLOOK.EXE'} | Format-List TimeCreated, Message
Сценарій 4. Події конкретної служби — Group Policy, PrintService
Application-and-Services Logs — це сотні окремих логів для кожного компонента. Їхні повні імена містять слеш (Microsoft-Windows-GroupPolicy/Operational).
Get-WinEvent -LogName 'Microsoft-Windows-GroupPolicy/Operational' -MaxEvents 20 | Select TimeCreated, Id, Message
Для пошуку імен логів за ключовим словом:
Get-WinEvent -ListLog '*GroupPolicy*' | Select LogName, RecordCount
Список усіх логів з подіями за останню добу:
Get-WinEvent -ListLog * | Where-Object {$_.RecordCount -gt 0 -and $_.LastWriteTime -gt (Get-Date).AddDays(-1)} | Sort LastWriteTime -Descending
Сценарій 5. Віддалений сервер
Get-WinEvent -FilterHashtable @{LogName='System'; Level=1,2; StartTime=(Get-Date).AddHours(-24)} -ComputerName DC01.corp.local -MaxEvents 30
Рівні 1 і 2 — Critical і Error. Масово за усіма DCs:
$dcs = Get-ADDomainController -Filter * | Select -Expand HostName
foreach ($dc in $dcs) {
$events = Get-WinEvent -FilterHashtable @{LogName='System'; Level=1,2; StartTime=(Get-Date).AddHours(-24)} -ComputerName $dc -ErrorAction SilentlyContinue
[PSCustomObject]@{
DC = $dc
CritErrorCount = $events.Count
}
}
Сценарій 6. XPath-фільтр для складних запитів
Коли FilterHashtable замалий (наприклад, шукати подію, де EventData містить конкретний SID), використовуйте XPath через -FilterXPath:
Get-WinEvent -LogName Security -FilterXPath "*[EventData[Data[@Name='SubjectUserName']='ivanov']]" -MaxEvents 50
XPath працює з уподобаною серверу XML-структурою події — дозволяє фільтрувати по будь-якому полю всередині EventData.
Типові пастки
-FilterHashtable strict про типиId=41 — працює. Id='41' (у лапках) — не працює. FilterHashtable пропускає значення в низькорівневе API, типи важливі. Якщо помилка «Parameter set cannot be resolved» — перевіряйте типи всіх значень.
-MaxEvents на великому часовому діапазоніБез -MaxEvents команда поверне ВСІ відповідні події. На сервері з мільйонами подій — десятки секунд і гігабайти RAM. Завжди ставте -MaxEvents N, починайте з 100 і збільшуйте за потребою.
TimeCreated повертається у локальному часі сервера. При агрегації з кількох DC у різних timezone — приводьте до UTC: $_.TimeCreated.ToUniversalTime().
Без прав адміна на цільовій машині Security-лог читається як «Access denied». Якщо запускаєтесь з непривілейованого облікового запису — отримуєте нічого, навіть не зрозумівши причини.
Коротка пам'ятка
- Останні 20 критичних/помилок System за день:
Get-WinEvent -FilterHashtable @{LogName='System'; Level=1,2; StartTime=(Get-Date).AddHours(-24)} -MaxEvents 20 - Reboot-related:
-Id 41,1074,6006,6008 - Account lockout:
-Id 4740у Security на PDC - Failed logon:
-Id 4625 - Application crash:
-ProviderName 'Application Error' - Знайти лог за ключовим словом:
Get-WinEvent -ListLog *keyword* - Віддалено: додати
-ComputerName HOST
Пов'язане
- ← Назад до Атласу команд Windows.
- Перевірка служб (попередня спиця) — разом з Get-WinEvent знаходять причину, чому служба впала.
- Active Directory: розслідування (майбутній цикл) — account lockout, replication errors, DNS-логи для AD.
Event Viewer — для обзору. Get-WinEvent — для роботи. Різниця особливо гостро відчувається, коли логи великі.