PowerShell 不打印到控制台

PowerShell not printing to console

我有下面的代码,可以在一定天数后检索最后登录的用户。我想阻止我不关心的登录出现在列表中,例如当它显示 "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" 这样的帐户的比较有什么问题?它总是评估为假,因此允许它被添加到列表
  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
            }
        }
    }
  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
        }
    }
}
  1. 无打印输出
    您正在将其捕获到 $Results 集合中。一行中的任何内容都会单独发送到输出流...而您正在捕获所有内容。

  2. 您的比较失败,因为您的正则表达式在 $Matches.AccountName 的末尾留下了 CR。我不知道如何修复正则表达式,所以我只是在上面使用 .Trim() 。在那之后,事情就成功了。

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

  3. foreach 中的内容发送到 $Results 变量
    发送到输出流的任何内容都可以分配给 $Var。在这种情况下,自定义对象被发送到输出流……PoSh 收集了所有输出,保留它直到循环结束,然后将对象填充到 [= 左侧的 $Var 中20=].


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

您的正则表达式有问题 - 它包括行尾 CR。我无法解决这个问题,所以我只是在上面使用了 .Trim()

您的 if 级联太曲折了,所以我简化了它以测试 -notin 排除的帐户列表。

#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

$Days 设置为 1,$Results 集合包含:

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