如何在 PowerShell 中使用 Get-WinEvent return 过滤 TaskDisplayName = 'Boot Performance Monitoring' 的事件日志条目

How to return filtered event log entries for TaskDisplayName = 'Boot Performance Monitoring' using Get-WinEvent in PowerShell

以下代码适用于 return Windows ID = 100 的日志事件。

$Date = (Get-Date).AddDays(-30)
Get-WinEvent -FilterHashTable @{ LogName = "Microsoft-Windows-Diagnostics-Performance/Operational"; StartTime = $Date; ID = 100 } -MaxEvents 1 | Select-Object -Property TimeCreated, Id, Task, TaskDisplayName, LevelDisplayName, Message

此代码 return 是 TaskDisplayName = 'Boot Performance Monitoring'

的错误
$Date = (Get-Date).AddDays(-30)
Get-WinEvent -FilterHashTable @{ LogName = "Microsoft-Windows-Diagnostics-Performance/Operational"; StartTime = $Date; TaskDisplayName = 'Boot Performance Monitoring' } | Select-Object -Property TimeCreated, Id, Task, TaskDisplayName, LevelDisplayName, Message

Get-WinEvent : No events were found that match the specified selection criteria. At D:\tfsws\TG-Dev-ICSG2\Support\PowerShell Scripts\Get-WinEvent-TEST.ps1:6 char:1 + Get-WinEvent -FilterHashTable @{ LogName = "Microsoft-Windows-Diagnos ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (:) [Get-WinEvent], Exception + FullyQualifiedErrorId : NoMatchingEventsFound,Microsoft.PowerShell.Commands.GetWinEventCommand

如何让 Get-WinEvent 接受 TaskDisplayName 过滤器?

Documentation 中所述,-FilterHashTable 仅允许一部分过滤器:

  • 日志名称=
  • 供应商名称=
  • 路径=
  • 关键字=
  • ID=
  • 等级=
  • 开始时间=
  • 结束时间=
  • 用户 ID=
  • 数据=
  • *=

您可以改为使用 -FilterXML 参数创建过滤器XML。 您可以使用 eventvwr.msc 创建适当的 XML(查找和示例事件,从详细信息视图中获取任务编号,配置协议过滤器,切换到 "XML" 选项卡,然后复制内容).

结果将是这样的:

$Filter = @'
<QueryList>
<Query Id="0" Path="Microsoft-Windows-Diagnostics-Performance/Operational">
    <Select Path="Microsoft-Windows-Diagnostics-Performance/Operational">*[System[(EventID=100) and (Task=4002)]]</Select>
</Query>
</QueryList>
'@
Get-WinEvent -FilterXml $Filter
然而,

TaskDisplayName 不是有效的 属性,您必须弄清楚 Task 编号 'Boot Performance Monitoring' 有什么。 请注意,Task 4002 不是您要查找的那个。这只是我的事件日志中唯一可用的数字。 ;)

或者,但性能不佳且不推荐(一般规则:左侧过滤器),您可以使用示例命令并添加 Where-Object 过滤器。

$FitlerHashTable =  @{ 
    LogName = "Microsoft-Windows-Diagnostics-Performance/Operational"
    StartTime = $Date
    ID = 100
}
Get-WinEvent -FilterHashTable $FitlerHashTable -MaxEvents 1 | 
Where-Object { $_.Task -eq 4002 } | 
Select-Object -Property TimeCreated, Id, Task, TaskDisplayName, LevelDisplayName, Message

很遗憾,您不能使用 -FilterHashTable 过滤 TaskDisplayName,原因有两个:

在 Microsoft 文档中 Get-WinEvent 有效的 FilterHashTable 值为:

  • LogName=<String[]>
  • ProviderName=<String[]>
  • Path=<String[]>
  • Keywords=<Long[]>
  • ID=<Int32[]>
  • Level=<Int32[]>
  • StartTime=<DateTime>
  • EndTime=<DataTime>
  • UserID=<SID>
  • Data=<String[]>

TaskDisplayName 不是 -FilterHashTable 选项之一....好的。因此,下一个选项是使用 -FilterXPath-FilterXML,这使我们可以访问一些更低级别的过滤。为简单起见,我将使用 -FilterXPath。为了找到要过滤的正确键,您必须转到事件的详细信息选项卡。这是一个示例事件:

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
    <Provider Name="Microsoft-Windows-Diagnostics-Performance" Guid="{CFC18EC0-96B1-4EBA-961B-622CAEE05B0A}" /> 
    <EventID>100</EventID> 
    <Version>2</Version> 
    <Level>2</Level> 
    <Task>4002</Task> 
    <Opcode>34</Opcode> 
    <Keywords>0x8000000000010000</Keywords> 
    <TimeCreated SystemTime="2018-05-23T21:09:42.047563100Z" /> 
    <EventRecordID>8</EventRecordID> 
    <Correlation ActivityID="{F774E0CC-F2D9-0006-E0FA-74F7D9F2D301}" /> 
    <Execution ProcessID="3876" ThreadID="4980" /> 
    <Channel>Microsoft-Windows-Diagnostics-Performance/Operational</Channel> 
    <Computer>D4700.adcfcu.connectfirstcu.com</Computer> 
    <Security UserID="S-1-5-19" /> 
</System>
<EventData>
    <Data Name="BootTsVersion">2</Data> 
    <Data Name="BootStartTime">2018-05-23T21:06:49.733345200Z</Data> 
    ..........
    <Data Name="UserLogonWaitDuration">9415</Data> 
</EventData>
</Event>

展开后,您会发现没有 TaskDisplayName。这是因为TaskDisplayName == Task Category。好的...让我们寻找 Task Category... 好吧也没有 Task Category。这是因为类别实际上以数字形式存储在事件中,然后使用 Event Category String 映射到适当的描述中。这就是为什么您不能基于 TaskDisplayNameTask Category 进行过滤的原因。相反,您必须过滤 Task 数字,在本例中为 4002。而如果你使用StartDate,即TimeCreated,你可以计算出30天是2592000000毫秒,那么你的代码就变成了:

Get-WinEvent -LogName "Microsoft-Windows-Diagnostics-Performance/Operational" -FilterXPath "*[System[Task=4002 and TimeCreated[timediff(@SystemTime) <= 2592000000]]]" | Select-Object -Property TimeCreated, Id, Task, TaskDisplayName, LevelDisplayName, Message