You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

核心问题分析

  1. 脚本块未执行,误判对象存在:将Get-WinEvent命令用{}包裹成脚本块(ScriptBlock),而非直接执行命令。脚本块本身是一个非空对象,导致if($eventInits -ne $null)和if($eventInitTerminate -ne $null)永远为真,强制进入错误分支。
  2. TimeCreated属性访问问题:直接访问$eventInit.TimeCreated可能因对象属性的封装方式导致空值,使用Select-Object -ExpandProperty TimeCreated可确保获取实际DateTime值。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 20:45:48