PowerShell не печатает на консоль - PullRequest
0 голосов
/ 10 февраля 2019

У меня есть код ниже, который возвращает последних пользователей, которые вошли в систему через определенное количество дней.Я хочу, чтобы имена входа, которые меня не волновали, не появлялись в списке, например, когда он показывает, что "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
            }
        }
    }

Ответы [ 2 ]

0 голосов
/ 10 февраля 2019
  1. Нет вывода на печать
    вы захватывали это в коллекцию $Results.что-либо в строке само по себе отправляется в выходной поток ... и вы захватываете все это.

  2. Ваше сравнение не удалось, потому что ваше регулярное выражение оставило CR в конце вашего$Matches.AccountName.Я не могу понять, как исправить регулярное выражение, поэтому я просто использовал .Trim() на нем.после этого все заработало.

    Однако вы использовали слишком сложный каскад IF.Я перешел на использование -notin $ExcludedAccountList для более простого теста.

  3. Отправка данных из foreach в $Results переменную
    Все, что отправляется в выходной поток, может бытьназначен на $Var.В этом случае пользовательский объект был отправлен в выходной поток ... и PoSh собрал весь этот вывод, удерживал его до завершения цикла и затем вставлял объекты в $Var слева от =.


Это немного другой способ получения информации.

Что-то не так с вашим регулярным выражением - оно включает в себя конец строки 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
0 голосов
/ 10 февраля 2019
  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
        }
    }
}
...