ค้นหาเว็บไซต์

การสืบค้นบันทึกเหตุการณ์ของ 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) &lt;= 2592000000]]]</Select>
</Query>
</QueryList>
'@
Get-WinEvent -FilterXML $xmlQuery

หากต้องการสร้างโค้ดคิวรี XML ที่ซับซ้อน คุณสามารถใช้คอนโซลกราฟิก Event Viewer:

  1. เรียกใช้คำสั่ง

    eventvwr.msc

    ;

  2. ค้นหาบันทึกที่คุณต้องการสร้างแบบสอบถามและคลิก กรองบันทึกปัจจุบัน

  3. เลือกพารามิเตอร์แบบสอบถามที่จำเป็นในแบบฟอร์มตัวกรอง ในตัวอย่างนี้ ฉันต้องการค้นหากิจกรรมที่มีรหัสเหตุการณ์เฉพาะในช่วง 7 วันที่ผ่านมาสำหรับผู้ใช้เฉพาะราย

  4. หากต้องการรับโค้ดคิวรี XML ให้ไปที่แท็บ XML แล้วคัดลอกโค้ด XPath (

    CTRL+A

    ,

    CTRL+C

    );

  5. คุณสามารถแก้ไขแบบสอบถามนี้ได้ด้วยตนเองหากจำเป็น

หากต้องการส่งออกรายการเหตุการณ์เป็นไฟล์ 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}
}

บทความที่เกี่ยวข้อง