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>.+)')
所以我有三个问题:
- 为什么 PowerShell 不在此位置打印任何内容?
- 我检查 AccountName 是否不等于像 "LOCAL SERVICE" 这样的帐户的比较有什么问题?它总是评估为假,因此允许它被添加到列表
- 这个有点离题,但是我对整个
$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
}
}
}
- 您将所有内容写入变量
$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
}
}
}
无打印输出
您正在将其捕获到 $Results
集合中。一行中的任何内容都会单独发送到输出流...而您正在捕获所有内容。
您的比较失败,因为您的正则表达式在 $Matches.AccountName
的末尾留下了 CR
。我不知道如何修复正则表达式,所以我只是在上面使用 .Trim()
。在那之后,事情就成功了。
但是,您使用了过于复杂的 IF 级联。我改用 -notin $ExcludedAccountList
进行更简单的测试。
将 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
我有下面的代码,可以在一定天数后检索最后登录的用户。我想阻止我不关心的登录出现在列表中,例如当它显示 "LOCAL SERVICE" 或 "NETWORK SERVICE" 已登录时。我还设计了它以排除重复。
在试图弄清楚为什么 Powershell 从未想过 $Matches.AccountName
等于 "LOCAL SERVICE" 或任何其他检查时,我意识到 powershell 拒绝在这一行之后打印任何内容
[void]($event.Message -match 'Account Name:\s{1,}(?<AccountName>.+)')
所以我有三个问题:
- 为什么 PowerShell 不在此位置打印任何内容?
- 我检查 AccountName 是否不等于像 "LOCAL SERVICE" 这样的帐户的比较有什么问题?它总是评估为假,因此允许它被添加到列表
- 这个有点离题,但是我对整个
$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
}
}
}
- 您将所有内容写入变量
$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
}
}
}
无打印输出
您正在将其捕获到$Results
集合中。一行中的任何内容都会单独发送到输出流...而您正在捕获所有内容。您的比较失败,因为您的正则表达式在
$Matches.AccountName
的末尾留下了CR
。我不知道如何修复正则表达式,所以我只是在上面使用.Trim()
。在那之后,事情就成功了。但是,您使用了过于复杂的 IF 级联。我改用
-notin $ExcludedAccountList
进行更简单的测试。将
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