You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PowerShell foreach循环中输出去重后的唯一结果列表?

解决Active Directory登录日志去重问题

嘿,我明白你的困扰——现在输出一堆重复的登录条目,想只保留唯一的记录对吧?问题出在你现在是直接用Write-Host把结果打印出来,没有把这些数据结构化存储,所以后面的Get-Unique根本没法作用在这些输出上(因为Write-Host的内容不会进入管道)。

咱们换个思路,先把所有符合条件的登录信息存成自定义对象,再对这些对象做去重操作,这样就能得到你想要的唯一结果了。

修改后的完整代码

# Find DC list from Active Directory
$DCs = Get-ADDomainController -Filter *
# Define time for report (default is 1 day)
$startDate = (Get-Date).AddDays(-1)
# 创建一个数组来存储结构化的登录记录
$loginRecords = @()

foreach ($DC in $DCs){
    $slogonevents = Get-Eventlog -LogName Security -ComputerName $DC.HostName -After $startDate -InstanceId 4624 | 
        Where-Object {$_.ReplacementStrings[5].ToLower() -eq "administrator"}
    
    foreach ($e in $slogonevents){
        if ($e.EventID -eq 4624 -and $e.ReplacementStrings[8] -in 3..10){
            if([ipaddress]::TryParse($e.ReplacementStrings[18],[ref][ipaddress]::Loopback)) {
                # 将每条记录封装成自定义对象
                $record = [PSCustomObject]@{
                    Type       = $e.ReplacementStrings[8]
                    IPAddress  = $e.ReplacementStrings[18]
                    HostName   = ([system.net.dns]::GetHostByAddress($e.ReplacementStrings[18])).HostName
                }
                # 添加到数组中
                $loginRecords += $record
            }
        }
    }
}

# 对结构化数据去重并输出
$loginRecords | Select-Object -Unique -Property Type, IPAddress, HostName

关键修改点说明

  • 新增了$loginRecords数组来存储每个登录记录的结构化对象,而不是直接打印字符串
  • 用[PSCustomObject]把Type、IP、主机名封装成属性,这样后续可以基于这些属性精准去重
  • 最后用Select-Object -Unique指定要去重的属性,确保只要这三个属性都相同的记录只保留一条

额外优化建议

如果担心DNS解析失败(比如某些IP无法反查主机名),可以加个try-catch块避免报错中断:

try {
    $hostName = ([system.net.dns]::GetHostByAddress($e.ReplacementStrings[18])).HostName
}
catch {
    $hostName = "无法解析主机名"
}

这样运行后,你就能得到每个唯一的登录条目啦!

内容的提问来源于stack exchange,提问作者ehh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:59:23