多OU查询AD禁用未登录计算机时的对象缺失与结果重复问题解决咨询
多OU查询AD禁用未登录计算机时的对象缺失与结果重复问题解决咨询
我来帮你拆解下遇到的两个核心问题:目标OU下的禁用计算机未出现在结果中,以及查询结果出现重复条目,结合你的代码和输出逐一分析解决:
一、结果重复的原因与解决方法
你的代码里同时指定了两个存在层级关系的OU:
$OUs = @( 'OU=DISABLED COMPUTERS,OU=DISABLED,DC=CONTOSO,DC=DOMAIN' 'OU=COMPUTERS,OU=DISABLED COMPUTERS,OU=DISABLED,DC=CONTOSO,DC=DOMAIN' )
而Get-ADComputer的默认搜索范围(SearchScope)是Subtree——也就是会递归查询当前OU及其所有子OU的对象。这就导致:
- 查询父OU(
DISABLED COMPUTERS)时,已经把子OU(COMPUTERS)里的所有计算机都查出来了 - 再单独查询子OU时,又把这些对象重复获取了一次
最终输出自然就出现了重复条目。
解决重复的两种方案:
只查询父OU即可
既然默认会递归子OU,完全不需要单独指定子OU,修改$OUs数组为只保留父OU:$OUs = @( 'OU=DISABLED COMPUTERS,OU=DISABLED,DC=CONTOSO,DC=DOMAIN' )这样一次查询就能获取父OU和所有子OU的符合条件的对象,不会重复。
限制搜索范围为当前OU的直接对象
如果确实需要同时查询多个独立OU(比如后续要扩展其他非层级OU),可以给Get-ADComputer加上-SearchScope OneLevel参数,让每个OU只查询直接下属的对象,不递归子OU:foreach ($OU in $OUs) { $inactiveComputers += Get-ADComputer -Properties LastLogonTimeStamp ` -Filter {LastLogonTimeStamp -lt $LastLogonDate -and serviceprincipalname -notlike "*MSClusterVirtualServer*" -and Enabled -eq $false } ` -SearchBase $OU ` -SearchScope OneLevel | Select-Object distinguishedName,Name, @{Name='LastLogonTimeStamp'; Expression={[DateTime]::FromFileTime($_.LastLogonTimeStamp)}} }
二、父OU下禁用计算机缺失的原因排查
你提到OU=DISABLED COMPUTERS下有一个禁用的计算机对象但未出现在结果中,大概率是这个对象不符合你的过滤条件,建议按以下步骤排查:
单独查询该对象,确认属性值
运行以下命令查看这个计算机的关键属性:Get-ADComputer -Identity "那个缺失的计算机名" -Properties LastLogonTimeStamp, Enabled, serviceprincipalname重点检查:
Enabled是否为False(确认是禁用状态)LastLogonTimeStamp是否存在,且转换为日期后确实早于90天前(如果该计算机从未登录过,LastLogonTimeStamp会是$null,这时候你的过滤条件LastLogonTimeStamp -lt $LastLogonDate会直接排除它)serviceprincipalname是否包含MSClusterVirtualServer(如果包含会被过滤掉)
调整过滤条件,兼容未登录过的计算机
如果该计算机从未登录过(LastLogonTimeStamp为$null),需要修改过滤条件,把这类对象也包含进来:-Filter { (LastLogonTimeStamp -lt $LastLogonDate -or LastLogonTimeStamp -notlike "*") -and serviceprincipalname -notlike "*MSClusterVirtualServer*" -and Enabled -eq $false }这里
LastLogonTimeStamp -notlike "*"用来匹配$null或者空值的情况。检查权限问题
确认运行脚本的账号是否有读取该计算机对象属性的权限,权限不足也可能导致对象无法被查询到。
修改后的完整示例代码
结合上面的优化,最终的脚本可以写成这样:
$LastLogonDate = (Get-Date).AddDays(-90) # 只查询父OU,自动递归子OU $OUs = @( 'OU=DISABLED COMPUTERS,OU=DISABLED,DC=CONTOSO,DC=DOMAIN' ) $inactiveComputers = @() foreach ($OU in $OUs) { $inactiveComputers += Get-ADComputer -Properties LastLogonTimeStamp ` -Filter { (LastLogonTimeStamp -lt $LastLogonDate -or LastLogonTimeStamp -notlike "*") -and serviceprincipalname -notlike "*MSClusterVirtualServer*" -and Enabled -eq $false } ` -SearchBase $OU | Select-Object distinguishedName,Name, @{Name='LastLogonTimeStamp'; Expression={ if ($_.LastLogonTimeStamp) { [DateTime]::FromFileTime($_.LastLogonTimeStamp) } else { "从未登录" } # 给未登录的对象标注说明 }} } # 如果需要导出到CSV,加上这行 $inactiveComputers | Export-Csv -Path "InactiveDisabledComputers.csv" -NoTypeInformation -Encoding UTF8 $inactiveComputers
内容来源于stack exchange
相关产品推荐
相关产品推荐

