การสืบค้นบันทึกเหตุการณ์ของ Windows ด้วย PowerShell
Windows Event Log เป็นเครื่องมือสำคัญสำหรับผู้ดูแลระบบในการติดตามข้อผิดพลาด คำเตือน และรายงานข้อมูลอื่นๆ ที่ระบบปฏิบัติการ ส่วนประกอบ หรือโปรแกรมบันทึกไว้ คุณสามารถใช้สแน็ปอิน MMC แบบกราฟิกของ Event Viewer (
eventvwr.msc) เพื่อดูบันทึกเหตุการณ์ของ Windows ในบางกรณี การใช้ PowerShell เพื่อแยกวิเคราะห์และวิเคราะห์ข้อมูลจากบันทึกเหตุการณ์จะสะดวกกว่ามาก ในบทความนี้ คุณจะได้เรียนรู้วิธีใช้ cmdlet Get-WinEvent เพื่อรับข้อมูลจากบันทึกเหตุการณ์ของ Windows
ขณะนี้มี cmdlet สองรายการสำหรับการเข้าถึงรายการบันทึกเหตุการณ์ใน Windows: Get-EventLog และ Get-WinEvent เราขอแนะนำให้คุณใช้ Get-WinEvent ในกรณีส่วนใหญ่ เนื่องจากเป็นวิธีที่มีประสิทธิภาพมากกว่า โดยเฉพาะอย่างยิ่งในสถานการณ์ที่คุณต้องประมวลผลเหตุการณ์จำนวนมากจากคอมพิวเตอร์ระยะไกล cmdlet Get-EventLog เลิกใช้แล้วและถูกใช้เพื่อรับบันทึกใน Windows รุ่นก่อนหน้า นอกจากนี้ Get-EventLog ยังไม่รองรับใน PowerShell Core 7.x เวอร์ชันล่าสุด
Get-WinEvent: ค้นหาบันทึกเหตุการณ์โดยใช้ PowerShell
หากต้องการใช้คำสั่ง Get-WinEvent คุณต้องเรียกใช้ PowerShell ในฐานะผู้ดูแลระบบ หากคุณพยายามเรียกใช้ Get-WinEvent ในฐานะผู้ใช้ที่ไม่ใช่ผู้ดูแลระบบ คุณจะไม่สามารถเข้าถึงบันทึกบางอย่าง รวมถึงบันทึกความปลอดภัย
ในการรับรายการเหตุการณ์จากบันทึกเฉพาะ คุณต้องระบุชื่อ ตัวอย่างเช่น คำสั่งต่อไปนี้แสดงรายการ 20 เหตุการณ์ล่าสุดจากบันทึกของระบบ:
Get-WinEvent -LogName Application -MaxEvents 20บันทึกระบบ แอปพลิเคชัน ความปลอดภัย หรือการตั้งค่าเป็นบันทึกที่ใช้บ่อยที่สุดในการค้นหา คุณยังสามารถระบุชื่อล็อกอื่นๆ คุณสามารถรับรายการบันทึกเหตุการณ์ทั้งหมดใน Windows ด้วยคำสั่ง:
Get-WinEvent -ListLog *ตัวอย่างเช่น หากต้องการดูประวัติการเชื่อมต่อ RDP บนคอมพิวเตอร์ คุณต้องระบุ
Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operationalบันทึก:
Get-WinEvent -LogName Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operationalหรือคุณสามารถรับบันทึกการเชื่อมต่อ SSH ใน Windows จากบันทึก OpenSSH/การปฏิบัติงาน:
Get-WinEvent -LogName OpenSSH/Operationalคุณยังสามารถเลือกเหตุการณ์จากบันทึกหลายรายการพร้อมกันได้อีกด้วย ตัวอย่างเช่น หากคุณต้องการรับข้อมูลเกี่ยวกับข้อผิดพลาดและคำเตือนจากบันทึกของระบบและแอปพลิเคชันในช่วง 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 )}คุณสามารถใช้ cmdlets 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 เร็วกว่าคำสั่งตัวกรอง Where-Object ปกติถึง 30 เท่า (
2.5วินาทีเทียบกับ
76วินาที)
หากคุณต้องการค้นหาเหตุการณ์ตาม EventID ให้ใช้คำสั่งต่อไปนี้กับพารามิเตอร์ FilterHashtable:
Get-WinEvent -FilterHashtable @{logname='System';id=1074}|ft TimeCreated,Id,Messageในตัวอย่างนี้ เราได้รับเหตุการณ์การรีบูตและปิดระบบ Windows ล่าสุด ทำให้เราสามารถระบุได้ว่าใครเป็นผู้รีบูตหรือปิดเครื่อง Windows
อาร์กิวเมนต์ FilterHashtable ช่วยให้คุณสามารถกรองตามแอตทริบิวต์เหตุการณ์ต่อไปนี้:
- LogName
- ProviderName
- Path
- Keywords (use 9007199254740992 to search for successful events and 4503599627370496 for failed ones)
- ID
- Level (1=FATAL, 2=ERROR, 3=Warning, 4=Information, 5=DEBUG, 6=TRACE, 0=Info)
- StartTime
- EndTime
- UserID (user’s SID)
- Data
ใช้คีย์เวิร์ด 9007199254740992 เพื่อค้นหาเหตุการณ์ที่ประสบความสำเร็จ และ 4503599627370496 สำหรับเหตุการณ์ที่ล้มเหลว
ต่อไปนี้คือตัวอย่างการค้นหาเหตุการณ์ในช่วงระยะเวลาหนึ่ง:
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;
ค้นหาบันทึกที่คุณต้องการสร้างแบบสอบถามและคลิก กรองบันทึกปัจจุบัน
เลือกพารามิเตอร์แบบสอบถามที่จำเป็นในแบบฟอร์มตัวกรอง ในตัวอย่างนี้ ฉันต้องการค้นหากิจกรรมที่มีรหัสเหตุการณ์เฉพาะในช่วง 7 วันที่ผ่านมาสำหรับผู้ใช้เฉพาะราย
หากต้องการรับโค้ดคิวรี XML ให้ไปที่แท็บ XML แล้วคัดลอกโค้ด XPath (
CTRL+A,
CTRL+C);
คุณสามารถแก้ไขแบบสอบถามนี้ได้ด้วยตนเองหากจำเป็น
หากต้องการส่งออกรายการเหตุการณ์เป็นไฟล์ CSV ให้ใช้ cmdlet ส่งออก 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}
}







