PowerShell脚本Get-WinEvent的TimeCreated为空及逻辑判断异常问题
PowerShell事件排查脚本问题修复
问题背景
测试一段PowerShell脚本,用于在事件查看器中查找特定事件并排除特定场景:
- 原脚本中事件创建时间(TimeCreated)输出为空,导致进入错误分支;
- 用
$initTime = $eventInit | Select-Object -Expand TimeCreated修复空值问题后,脚本仍错误判定存在Terminate事件(实际测试时间段内无此类事件),错误进入对应分支; - 脚本目标:排除SlotBroker事件与chromoting事件之间存在Terminate事件的情况;
- 限制:目标机器无PowerShellISE,无法单步调试。
原始脚本
#Look for crash within 150 hours of boot, and with Init within 7 minutes before that $today=[system.datetime](Get-Date) $startTime=$today.AddHours(-150) $events = Get-WinEvent -FilterHashtable @{LogName='Application';ProviderName='SlotBroker';StartTime=$($startTime);EndTime=$($today);} -ErrorAction SilentlyContinue if($events -ne $null) { foreach ($event in $events) { $crashOccurredTime=$event.TimeCreated $lookForInitStart = $event.TimeCreated.AddMinutes(-7) $eventInits = {Get-WinEvent -FilterHashtable @{LogName='Application';ProviderName='chromoting';StartTime=$lookForInitStart;EndTime=$crashOccurredTime;} -ErrorAction SilentlyContinue } if($eventInits -ne $null) { foreach ($eventInit in $eventInits) { #check that didn't have Terminate in that timeframe because we don't want this case #look for exclude case of Terminate between Init and crash $initTime = $eventInit.TimeCreated #chromoting Write-Host "initTime $($initTime)" ##this is blank time $eventInitTerminate = {Get-WinEvent -FilterHashtable @{LogName='Application';ProviderName='AppMgr';StartTime=$initTime;EndTime=$crashOccurredTime;} -ErrorAction SilentlyContinue | Where-Object {(-PipelineVariable Message -Match 'Terminate function called') -or (-PipelineVariable Message -Match 'Terminate function returned')} } if($eventInitTerminate -ne $null) { #it always falls in here no matter if it should or not. Write-Host "Found application.exe after Init with Terminate TimeCreatedCrash $($event.TimeCreated) ProviderName $($event.ProviderName) Message $($event.Message) TerminateTime $($eventInitTerminate.TimeCreated)" } else #this will print { Write-Host "Found application.exe after Init without Terminate TimeCreated $($event.TimeCreated) ProviderName $($event.ProviderName) Message $($event.Message) InitTime $($eventInit.TimeCreated)" } } #foreach } }
测试用事件日志示例
Error 8/11/2022 9:43 SlotBroker Information 8/11/2022 9:37 chromoting Information 8/11/2022 9:36 AlarmSoundHelper
核心问题分析
- 脚本块未执行,误判对象存在:将
Get-WinEvent命令用{}包裹成脚本块(ScriptBlock),而非直接执行命令。脚本块本身是一个非空对象,导致if($eventInits -ne $null)和if($eventInitTerminate -ne $null)永远为真,强制进入错误分支。 - TimeCreated属性访问问题:直接访问
$eventInit.TimeCreated可能因对象属性的封装方式导致空值,使用Select-Object -ExpandProperty TimeCreated可确保获取实际DateTime值。 - Where-Object语法错误:错误使用
-PipelineVariable Message,应直接引用事件对象的Message属性($_.Message)进行匹配。
修复后的脚本
# 查找启动后150小时内的崩溃事件,且崩溃前7分钟内存在Init事件 $today = Get-Date $startTime = $today.AddHours(-150) $events = Get-WinEvent -FilterHashtable @{ LogName = 'Application' ProviderName = 'SlotBroker' StartTime = $startTime EndTime = $today } -ErrorAction SilentlyContinue if ($events) { foreach ($event in $events) { $crashOccurredTime = $event.TimeCreated $lookForInitStart = $crashOccurredTime.AddMinutes(-7) # 直接执行Get-WinEvent,移除不必要的脚本块封装 $eventInits = Get-WinEvent -FilterHashtable @{ LogName = 'Application' ProviderName = 'chromoting' StartTime = $lookForInitStart EndTime = $crashOccurredTime } -ErrorAction SilentlyContinue if ($eventInits) { foreach ($eventInit in $eventInits) { # 正确获取TimeCreated属性值 $initTime = $eventInit | Select-Object -ExpandProperty TimeCreated Write-Host "initTime $initTime" # 修复Where-Object语法,直接匹配事件Message属性 $eventInitTerminate = Get-WinEvent -FilterHashtable @{ LogName = 'Application' ProviderName = 'AppMgr' StartTime = $initTime EndTime = $crashOccurredTime } -ErrorAction SilentlyContinue | Where-Object { $_.Message -match 'Terminate function called' -or $_.Message -match 'Terminate function returned' } # 准确判断是否存在Terminate事件 if ($eventInitTerminate) { Write-Host "检测到Init后存在Terminate事件 - 崩溃时间: $crashOccurredTime | 事件提供者: $($event.ProviderName) | 事件内容: $($event.Message)" } else { Write-Host "Init后无Terminate事件 - 崩溃时间: $crashOccurredTime | 事件提供者: $($event.ProviderName) | 事件内容: $($event.Message) | Init时间: $initTime" } } } } }
额外优化说明
- 使用
if ($events)替代if($events -ne $null),PowerShell中对集合/对象的布尔判断更简洁准确; - 格式化脚本结构,提升可读性;
- 简化日志输出内容,信息更直观清晰。
内容的提问来源于stack exchange,提问作者Michele
相关产品推荐
相关产品推荐

