首页 > 解决方案 > 使用 Get-WinEvent / Get-EventLog 查询事件日志在查询关机事件 1074 时非常慢

问题描述

我正在编写一个 PowerShell 脚本,该脚本需要能够获取System事件日志的查询并找到事件 ID 为 1074的事件,该事件表示关闭。

为此,我使用了以下代码,但是,我注意到在具有较大System事件日志的服务器上运行代码时,该命令需要几秒钟才能完成。

Get-WinEvent -LogName 'System' | Where-Object { $_.Id -eq 1074 }

有没有办法提高这段代码的性能?

标签: windowspowershell

解决方案


Get-WinEvent 与 Get-EventLog

您可以获得的第一个性能提升是使用Get-WinEventover Get-EventLog。那是因为Get-WinEvent正在更换Get-EventLog并且应该表现更好

正确过滤查询

我找到了Ed Wilson 的一篇精彩文章,其中详细介绍了如何提高查询的性能,例如我在上面发布的查询。我将重点介绍我为大大提高脚本性能所做的性能调整。

  1. 不要使用-LogName参数,而是使用-ProviderName生成您要查找的事件的提供程序的适当参数(Ed 的博客文章详细介绍了如何找到它)。就我而言,我需要使用User32提供程序,因为它是生成1074我感兴趣的事件的提供程序。
  2. 尽可能避免完全遍历数据。你会注意到我的脚本有一个Where-Object子句。该子句将遍历输入它的所有事件,仅查找具有1074Id 的事件。为避免这种情况,Get-WinEvent 有一个-FilterHashtable参数,可用于在Get-WinEventcmdlet 中过滤查询结果,从而提高效率。正如 Microsoft 文档中所引用的:“当您使用大型事件日志时,将对象沿管道发送到 Where-Object 命令效率不高。”

编码

我已经实现了上述概念并对每个概念进行了定时改进,以显示使用带有参数的Measure-Commandcmdlet 的性能差异。-Expression请注意,我正在测试的机器在System日志中有 23,581 个事件。

基线

Measure-Command -Expression {
    Get-WinEvent -LogName 'System' | Where-Object { $_.Id -eq 1074 }
}

# TotalSeconds      : 7.600536

使用ProviderNamevsLogName

Measure-Command -Expression {
    Get-WinEvent -ProviderName 'User32' | Where-Object { $_.Id -eq 1074 }
}

# TotalSeconds      : 0.1929325

使用FilterHashtable

Measure-Command -Expression {
    Get-WinEvent -FilterHashtable @{ProviderName = "User32"; Id = 1074} 
}

# TotalSeconds      : 0.1578928

推荐阅读