我有下面的代码,该代码在一定天数后检索最后一个要登录的用户。我想停止我不关心的登录名出现在列表中,例如当它显示“ LOCAL SERVICE”或“ NETWORK SERVICE”已登录时。我还对其进行了设计,以免重复。 >
在试图弄清楚为什么Powershell从未想到$Matches.AccountName
等于“ LOCAL SERVICE”或任何其他检查时,我意识到Powershell拒绝在此行之后打印任何内容
[void]($event.Message -match 'Account Name:\s{1,}(?<AccountName>.+)')
所以我有三个问题:
$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
}
}
}
答案 0 :(得分:2)
无打印输出
您正在将其捕获到$Results
集合中。一行上的所有内容本身都会发送到输出流中……而您正在捕获所有内容。
您的比较失败,因为您的正则表达式在CR
的末尾留下了$Matches.AccountName
。我不知道如何修复正则表达式,因此我只在其上使用了.Trim()
。之后,一切正常。
但是,您使用了过于复杂的IF级联。我改用-notin $ExcludedAccountList
进行更简单的测试。
将内容从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)
$result
,因此没有任何内容打印到控制台上$arr
是一个空数组,我看不出有任何理由在此处使用数组。而且,比较时间太长,很难发现缺陷。您可以做得多简单,我将在稍后展示。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
}
}
}