PowerShell函数查询AD未登录计算机返回空列表问题求助
问题诊断与修复
你的函数返回空结果的核心问题是Group-Object后的过滤逻辑错误,同时还有几个次要的语法/逻辑问题,下面逐一说明:
1. 核心错误:Group-Object后的属性访问错误
Group-Object Name会将同一计算机的多DC查询结果分组,生成的组对象包含Name、Count、Group属性,没有直接的LastLogon属性。你原代码中的Where-Object LastLogon -ge $inactiveDateValue是在过滤不存在的属性,PowerShell会将未定义的属性视为$null,而$null -ge 任意值的结果是$false,因此返回空;当改为-le时,$null -le 任意值结果为$true,所以返回所有组,即全部计算机。
正确的逻辑是:对每个计算机组,提取组内所有LastLogon值的最大值(即该计算机的最新登录时间),再判断这个最大值是否早于/等于你设定的不活跃阈值(因为你要找的是长时间未登录的机器,即最新登录时间在$inactiveDate之前)。
2. 次要问题:AD Filter的变量解析错误
Get-ADComputer -Filter 'Enabled -eq $true'中的单引号会阻止$true的变量解析,AD服务会将$true视为字符串,而非布尔值,导致过滤条件失效。应该改用双引号,或者直接写AD语法认可的TRUE。
3. 冗余的日期转换
[System.DateTime]$todaysDate = (Get-Date -Format d)将日期转为字符串再转回DateTime是完全冗余的,直接用Get-Date即可完成日期计算。
修正后的函数代码
Function Get-OldNames { # 查询指定OU中长时间未登录的启用状态计算机,聚合所有DC的LastLogon数据获取最新登录时间 [CmdletBinding()] param( # 目标OU的LDAP路径 [string]$TargetOU = "OU=Computers,OU=NewYork,OU=US,DC=contoso,DC=com", # 未活跃天数(负数表示向前推N天) [int]$InactiveDays = -90 ) # 计算不活跃阈值的FileTime格式(AD存储LastLogon的格式) $inactiveDate = (Get-Date).AddDays($InactiveDays) $inactiveDateFileTime = $inactiveDate.ToFileTime() # 获取所有域控制器 $domainControllers = Get-ADDomainController -Filter * # 聚合所有DC的计算机登录数据 $allComputerLogs = foreach ($dc in $domainControllers) { Write-Host "Querying $($dc.Name)..." Get-ADComputer -Filter "Enabled -eq $true" -SearchBase $TargetOU -Server $dc.Name -Properties LastLogon | Select-Object Name, LastLogon, @{Name='LastLogonAsDate';Expression={ # 处理LastLogon为0的情况(从未登录过的计算机) if ($_.LastLogon -eq 0) { [DateTime]::MinValue } else { [DateTime]::FromFileTime($_.LastLogon) } }} } # 按计算机名分组,提取每组最新的登录时间,筛选未活跃机器 $inactiveComputers = $allComputerLogs | Group-Object Name | ForEach-Object { # 获取该计算机的最新LastLogon(FileTime值越大时间越新) $latestLogon = $_.Group | Sort-Object LastLogon -Descending | Select-Object -First 1 # 判断最新登录时间是否早于阈值 if ($latestLogon.LastLogon -le $inactiveDateFileTime) { [PSCustomObject]@{ Name = $_.Name LatestLastLogon = $latestLogon.LastLogonAsDate DomainController = $latestLogon.PSComputerName } } } # 返回结果(如果只需要名称,可改为return $inactiveComputers.Name) return $inactiveComputers }
关键改进说明
- 改为使用
Param()块定义参数,提升函数的灵活性和可复用性 - 处理了
LastLogon为0的边界情况(从未登录的计算机) - 分组后正确提取每个计算机的最新登录记录,并与阈值对比
- 修复了AD Filter的变量解析问题
- 返回包含更多信息的自定义对象(如需仅返回名称,直接取
$inactiveComputers.Name即可)
内容的提问来源于stack exchange,提问作者Ed R.
相关产品推荐
相关产品推荐

