【问题标题】:Get-WinEvent search for all errorsGet-WinEvent 搜索所有错误
【发布时间】:2022-06-16 02:38:50
【问题描述】:

运行 Get-WinEvent 可以使用通配符:

Get-WinEvent -filterhashtable 
@{logname="*";providername="*cluster*";starttime="04.01.2022";endtime="05.31.2022";level=2} - 
ErrorAction SilentlyContinue

但对 logname 和 providername 仅使用通配符(令人惊讶的是)不会返回任何记录:

Get-WinEvent -filterhashtable 
@{logname="*";providername="*";starttime="04.01.2022";endtime="05.31.2022";level=2} - 
ErrorAction SilentlyContinue

所以:如何在给定时间跨度内从每个提供者的每个日志中搜索所有错误?

【问题讨论】:

    标签: powershell


    【解决方案1】:

    我将如何使用 foreach-object 循环来做到这一点。所有日志名应涵盖所有提供者。在 powershell 7 中,您可以执行 foreach-object -parallel,我花了不到 2 秒的时间。尝试枚举级别;我很惊讶它仍然需要转换为 int。

    $list = 1..10 | % tostring comp000
    invoke-command $list {  # runs in parallel
      get-winevent -listlog * -ea 0 | 
      % { Get-WinEvent @{logname=$_.logname; 
      starttime='4/1'; endtime='5/31'; 
      level=[int][Diagnostics.Tracing.EventLevel]::Error} -ea 0 } 
    }
    

    【讨论】:

    • 不错!不幸的是,我在该服务器上没有 PS 7,防火墙被阻止,所以我只能将脚本与“invoke-command....”等一起使用,所以它“需要”时间..
    • 嗯,没有 -parallel 只需要 9 秒。请注意,invoke-command comp1,comp2,comp3 本身是并行运行的。
    【解决方案2】:

    StartTimeEndTime 的类型应为 DateTime,但您提供的 字符串 可能会或可能不会转换为日期时间对象。
    Get-WinEvent参数-FilterHashtable

    由于为参数 LogNameProviderName 提供单个通配符 * 显然不起作用,您可以首先检索系统中存在的所有有效日志名和提供程序名称作为字符串数组并使用它们:

    # get an array of all Log names
    $logNames     = [string[]](Get-WinEvent -ListLog *).LogName
    # below line is bound to give you exceptions, so use SilentlyContinue
    $logProviders = [string[]](Get-WinEvent -ListProvider * -ErrorAction SilentlyContinue).Name
    
    $startDate    = (Get-Date -Year 2022 -Month 4 -Day 1).Date  # set to midnight
    $endDate      = $startDate.AddMonths(2).AddDays(-1)         # calculate 2 months duration    
    $filter       = @{LogName=$logNames; ProviderName=$logProviders; StartTime=$startDate; EndTime=$endDate; Level=2}
    Get-WinEvent -FilterHashtable $filter -ErrorAction SilentlyContinue 
    

    使用开始和结束日期作为字符串,如"04.01.2022" 可以在您的系统中工作,但如果您在世界的不同地方,因此使用不同的系统语言环境,这些字符串很可能无法转换为 DateTime 对象。因此,最好使用文档中所述的正确数据类型。


    根据docs参数LogName:

    “Get-WinEvent cmdlet 查询限制为 256 的 Windows API。这会使一次过滤所有日志变得困难。您可以通过使用循环进行迭代来解决此问题通过每个日志",

    也许更好地使用像这样的循环

    # below line is bound to give you exceptions, so use SilentlyContinue
    $logProviders = [string[]](Get-WinEvent -ListProvider * -ErrorAction SilentlyContinue).Name
    $startDate    = (Get-Date -Year 2022 -Month 4 -Day 1).Date  # set to midnight
    $endDate      = $startDate.AddMonths(2).AddDays(-1)         # calculate 2 months duration 
    
    Get-WinEvent -ListLog * | ForEach-Object {
        $filter = @{LogName=$_.LogName; ProviderName=$logProviders; StartTime=$startDate; EndTime=$endDate; Level=2}
        Get-WinEvent -FilterHashtable $filter -ErrorAction SilentlyContinue
    }
    

    【讨论】:

    • @nimizen: "04.01.2022" 是一个字符串,但是合法的日期条目,它在第一个示例中效果很好 (...logname="";providername="*cluster i>"...) 回馈一些记录,所以这绝对不是问题。
    • 我同意,这不是问题,但这是 Theo 的答案,我只是编辑了它,因为代码格式不正确。 Microsoft 文档确实表明 ProviderName 应该采用通配符,但在我的测试中,它仍然需要至少一个字母数字字符才能正常运行并返回结果。在没有“ContinueSilently”的情况下运行您的代码确实会产生一些错误输出,您可以使用这些错误输出进行进一步调查。
    • 是的,这可能是重点:必须至少有一个字母数字字符,所以还有一个问题:如何显示给定时间跨度内的所有错误?
    • @Purclot 请看我的编辑
    • 谢谢,它适用于循环,但性能是..怎么说...不是最快的.. ;-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多