PowerShell无法打印到控制台

时间:2019-02-10 07:29:13

标签: powershell foreach event-viewer

我有下面的代码,该代码在一定天数后检索最后一个要登录的用户。我想停止我不关心的登录名出现在列表中,例如当它显示“ LOCAL SERVICE”或“ NETWORK SERVICE”已登录时。我还对其进行了设计,以免重复。 >

在试图弄清楚为什么Powershell从未想到$Matches.AccountName等于“ LOCAL SERVICE”或任何其他检查时,我意识到Powershell拒绝在此行之后打印任何内容

[void]($event.Message -match 'Account Name:\s{1,}(?<AccountName>.+)')

所以我有三个问题:

  1. 为什么PowerShell无法在该位置打印任何内容?
  2. 检查AccountName是否等于“ LOCAL SERVICE”之类的帐户的比较有什么问题?它始终计算为false,因此可以将其添加到列表中
  3. 这是一个有点偏离主题的话题,但是我对整个$result = foreach($event in $events)所做的事情有什么名字吗?我不太了解它是如何工作的,或者它不知道如何将$result的每个索引设置为等于
{
    $computer = $env:ComputerName
    if ($Days -eq $null) {
        $Days = Read-Host -prompt "Enter the number of days to go back"
    }
    $startDate = (Get-Date) - (New-TimeSpan -Day $Days)
    $events = Get-WinEvent -Computer $computer -FilterHashtable @{Logname='Security';ID=4672;StartTime=$startDate}

    [System.Collections.ArrayList]$arr = @() 
    $result = foreach ($event in $events) {
        [void]($event.Message -match 'Account Name:\s{1,}(?<AccountName>.+)')
        $Matches.AccountName.gettype()
        $Matches.AccountName
        "SYSTEM"
        $h = Read-Host -prompt "Stop here to see if anything printed"
        if ((-not ($arr.Contains($Matches.AccountName))) -and ($Matches.AccountName -ne "SYSTEM") -and ($Matches.AccountName -ne "LOCAL SERVICE") -and ($Matches.AccountName -ne "NETWORK SERVICE") -and ($Matches.AccountName -ne "Local Administrator")) {
            $arr.Add($Matches.AccountName) > $null;
            [PSCustomObject]@{
                AccountName = $Matches.AccountName;
                Time = $event.timeCreated
            }
        }
    }

2 个答案:

答案 0 :(得分:2)

  1. 无打印输出
    您正在将其捕获到$Results集合中。一行上的所有内容本身都会发送到输出流中……而您正在捕获所有内容。

  2. 您的比较失败,因为您的正则表达式在CR的末尾留下了$Matches.AccountName。我不知道如何修复正则表达式,因此我只在其上使用了.Trim()。之后,一切正常。

    但是,您使用了过于复杂的IF级联。我改用-notin $ExcludedAccountList进行更简单的测试。

  3. 将内容从foreach发送到$Results变量
    发送到输出流的任何内容都可以分配给$Var。在这种情况下,自定义对象被发送到输出流...并且PoSh收集了所有输出,一直保持到循环结束,然后将这些对象塞入{{ 1}}。


这里获取信息的方式略有不同。

您的正则表达式有问题-它包含行尾$Var。我无法解决此问题,因此仅在其上使用了=

您的CR级联过于曲折,因此我简化了测试.Trim()的排除帐户列表。

if

-notin设置为1的情况下,#Requires -RunAsAdministrator $ExcludedAccountList = @( # I only have the "system" account listed # commented this out so I could see something #'SYSTEM' 'LOCAL SERVICE' 'NETWORK SERVICE' 'Local Administrator' ) $computer = $env:ComputerName $Days = '' if ($Days -eq '') { [int]$Days = Read-Host -prompt "Enter the number of days to go back" } $startDate = (Get-Date).AddDays(-$Days) $FilterHashtable = @{ Logname = 'Security' ID = 4672 StartTime = $startDate } $EventList = Get-WinEvent -Computer $computer -FilterHashtable $FilterHashtable $DupeCheck = [System.Collections.Generic.List[string]]::New() # force the $Var to be an array even if only one item is returned [array]$Results = foreach ($Event in $EventList) { $null = $event.Message -match 'Account Name:\s{1,}(?<AccountName>.+)' # get rid of trailing non-printing char [hex = "0d" - carriage return] $AccountName = $Matches.AccountName.Trim() # check if we already have that account name # then exclude the unwanted account names if (-not $DupeCheck.Contains($AccountName) -and $AccountName -notin $ExcludedAccountList) { $DupeCheck.Add($AccountName) [PSCustomObject]@{ AccountName = $AccountName Time = $event.timeCreated } } #> } $Results 集合包含以下内容:

AccountName Time
----------- ----
SYSTEM      2019-02-10 1:11:52 AM

答案 1 :(得分:0)

  1. 您将所有内容都写入了变量$result,因此没有任何内容打印到控制台上
  2. $arr是一个空数组,我看不出有任何理由在此处使用数组。而且,比较时间太长,很难发现缺陷。您可以做得多简单,我将在稍后展示。
  3. 我不知道是否有名称,但是它的作用是将所有输出写入变量。如果这样做,则应注意仅存储一种类型的对象。在您的情况下,您存储几个字符串,然后存储一个PSCustomObject

通过使用-contains-notcontains运算符,它可以检查数组中是否存在元素,可以更轻松,更容易地解决问题。 因此,只需创建一个要过滤掉的帐户数组,检查找到的帐户是否在过滤器列表中,然后继续。这样一来,您也不必麻烦地扩展列表甚至将列表作为函数输入的一部分。

$FilteredAccounts = 'LOCAL SERVICE', 'NETWORK SERVICE'
$AccountRegEx = 'Account Name:\s{1,}(?<AccountName>.+)'

foreach ($Event in $Events) {
    [void]($Event.Message -match $AccountRegEx)
    if ($FilteredAccounts -notcontains $Matches.AccountName.Trim()) {
        [PSCustomObject]@{
            AccountName = $Matches.AccountName
            Time = $Event.TimeCreated
        }
    }
}