PowerShell Get-WinEvent字段查询与筛选脚本故障排查求助
解决PowerShell Get-WinEvent筛选与字段提取问题
一、先修复你现有脚本的核心问题
你的脚本目前有两个关键问题导致不符合预期:
- 逻辑运算符优先级错误:Where-Object里的条件没有分组,
-or的作用范围会超出预期,必须把两个条件组分别用括号括起来。 - Export-CSV的变量错误:
$_.basename是文件对象的属性,但当前管道里的对象是事件日志条目,这里会直接报错,得先定义好输出文件名。
修复后的基础筛选脚本如下:
$EventlogTempFolder = "c:\temp\" $outputFile = Join-Path $EventlogTempFolder "filtered_events.csv" Get-WinEvent -FilterHashtable @{Path="c:\temp\test.evtx";} | Where-Object { ($_.Id -eq 4624 -and $_.Properties[8].Value -eq 2) -or ($_.Id -eq 4625) } | Export-Csv -Path $outputFile -Encoding UTF8 -NoTypeInformation -Force
二、获取Get-WinEvent的所有字段列表
要拿到事件的全部可用字段,有两种实用方法:
1. 查看事件对象的原生属性
取一条测试事件,用Get-Member列出它的所有内置属性:
Get-WinEvent -FilterHashtable @{Path="c:\temp\test.evtx"; Id=4624} -MaxEvents 1 | Get-Member
这会展示事件对象的原生属性,比如Id、TimeCreated、MachineName、Level、Properties等。
2. 解析Properties集合中的详细字段
安全事件(如4624/4625)的核心细节都存在Properties集合里,每个索引对应一个具体字段。你可以用下面的命令展开所有属性并查看对应值:
Get-WinEvent -FilterHashtable @{Path="c:\temp\test.evtx"; Id=4624} -MaxEvents 1 | Select-Object -Property *, @{ Name = "AllProperties" Expression = { $propDict = @{} for ($i=0; $i -lt $_.Properties.Count; $i++) { $propDict["Property_$i"] = $_.Properties[$i].Value } $propDict } } | ConvertTo-Json -Depth 3
这样会以JSON格式展示所有原生属性,加上每个Properties索引对应的具体值。你可以根据输出对应每个索引的含义,比如4624的Property[8]是LogonType,Property[19]是源IP地址等。
三、满足你完整需求的最终脚本
下面的脚本实现了所有要求:筛选指定事件、提取全部字段、添加本地/远程标记、提取网络数据:
$EventlogTempFolder = "c:\temp\" $outputFile = Join-Path $EventlogTempFolder "logon_events_detailed.csv" Get-WinEvent -FilterHashtable @{Path="c:\temp\test.evtx";} | Where-Object { ($_.Id -eq 4624 -and $_.Properties[8].Value -eq 2) -or ($_.Id -eq 4625) } | Select-Object -Property *, # 添加本地/远程登录标记 @{Name="LogonLocation"; Expression={ if ($_.Id -eq 4624) { # LogonType=2为本地交互式登录,标记为local if ($_.Properties[8].Value -eq 2) { "local" } else { "remote" } # 若需要判断其他远程LogonType可扩展此处 } else { # 4625失败登录:源IP为空则是本地,否则为远程 if ([string]::IsNullOrEmpty($_.Properties[19].Value)) { "local" } else { "remote" } } }}, # 提取核心网络数据字段 @{Name="SourceIP"; Expression={$_.Properties[19].Value}}, @{Name="TargetUsername"; Expression={$_.Properties[5].Value}}, @{Name="TargetHostname"; Expression={$_.Properties[11].Value}}, # 展开所有Properties为单独列(确保获取全部字段) @{Name="Property0"; Expression={$_.Properties[0].Value}}, @{Name="Property1"; Expression={$_.Properties[1].Value}}, @{Name="Property2"; Expression={$_.Properties[2].Value}}, @{Name="Property3"; Expression={$_.Properties[3].Value}}, @{Name="Property4"; Expression={$_.Properties[4].Value}}, @{Name="Property5"; Expression={$_.Properties[5].Value}}, @{Name="Property6"; Expression={$_.Properties[6].Value}}, @{Name="Property7"; Expression={$_.Properties[7].Value}}, @{Name="Property8"; Expression={$_.Properties[8].Value}}, @{Name="Property9"; Expression={$_.Properties[9].Value}}, @{Name="Property10"; Expression={$_.Properties[10].Value}}, @{Name="Property11"; Expression={$_.Properties[11].Value}}, @{Name="Property12"; Expression={$_.Properties[12].Value}}, @{Name="Property13"; Expression={$_.Properties[13].Value}}, @{Name="Property14"; Expression={$_.Properties[14].Value}}, @{Name="Property15"; Expression={$_.Properties[15].Value}}, @{Name="Property16"; Expression={$_.Properties[16].Value}}, @{Name="Property17"; Expression={$_.Properties[17].Value}}, @{Name="Property18"; Expression={$_.Properties[18].Value}}, @{Name="Property19"; Expression={$_.Properties[19].Value}}, @{Name="Property20"; Expression={$_.Properties[20].Value}}, @{Name="Property21"; Expression={$_.Properties[21].Value}} | Export-Csv -Path $outputFile -Encoding UTF8 -NoTypeInformation -Force
脚本说明:
- 修正了Where-Object的逻辑分组,确保筛选条件准确
- 新增
LogonLocation列,根据事件类型和字段值自动标记local或remote - 提取了
SourceIP、TargetUsername、TargetHostname等核心网络相关字段 - 展开了
Properties集合的所有索引为单独列,确保你能获取到事件的全部字段 - 输出UTF8编码的CSV文件,避免乱码问题
后续如果需要选择特定字段,只需修改Select-Object里的属性列表,删除不需要的列即可。
内容的提问来源于stack exchange,提问作者Peter Core
相关产品推荐
相关产品推荐

