为何PowerShell获取域内PC最后登录时间远慢于AD Tidy?
嘿,这个问题我太有共鸣了!之前用PowerShell搞AD资产排查的时候,也碰到过这种慢到离谱的情况,咱们来掰扯清楚AD Tidy为啥快,以及你的PowerShell脚本慢在哪里,还有怎么优化。
为什么你的PowerShell脚本这么慢?
- 核心问题是串行+重复查询:你现在是遍历3000台客户端,每台还要遍历35台DC逐个查询,相当于105000次独立查询,每次2秒,总时间自然爆炸。
- 另外,默认的
Get-ADComputer如果不指定属性,会返回很多冗余数据,增加传输和处理时间;而且没有利用AD的域同步机制,非要查所有DC,其实很多DC的lastLogon数据是过时的。
AD Tidy实现快速查询的核心技巧
AD Tidy能在15分钟搞定,主要是用了这些优化手段:
- 只查关键DC(优先PDC Emulator):域的PDC模拟器是负责时间同步、密码变更、交互式登录的核心DC,所有客户端的登录事件都会优先同步到PDC,所以PDC上的
lastLogon数据是最及时的,完全不用查其他34台DC。 - 批量LDAP查询:AD Tidy底层用的是优化过的LDAP协议,一次性批量查询所有计算机对象,只请求
lastLogon、lastLogonTimestamp这些需要的属性,避免了单台逐个查询的开销。 - 利用可复制属性(可选):如果对登录时间的实时性要求不是100%(允许14天内的滞后),它会直接读取
lastLogonTimestamp属性——这个属性是会在域内所有DC之间复制的,不需要查多个DC,瞬间就能拿到所有数据。 - 并行处理:后台会并行处理多个查询请求,而不是像你的脚本那样串行等待,进一步压缩时间。
PowerShell脚本的优化方案
照着AD Tidy的思路改,你的脚本速度能提升几百倍:
- 锁定PDC模拟器查询
先获取域的PDC,所有查询都指向它:$pdc = (Get-ADDomain).PDCEmulator - 批量查询+只取需要的属性
一次性拉取所有计算机,指定属性减少数据传输:$allComputers = Get-ADComputer -Filter * -Properties lastLogon, lastLogonTimestamp -Server $pdc - 格式化输出结果
把二进制的FileTime转成可读日期,加上查询的DC:$allComputers | Select-Object Name, @{Name='LastLogon'; Expression={[DateTime]::FromFileTime($_.lastLogon)}}, @{Name='LastLogonTimestamp'; Expression={[DateTime]::FromFileTime($_.lastLogonTimestamp)}}, @{Name='QueryDC'; Expression={$pdc}} - 并行处理(可选,PowerShell 7+支持)
如果PDC压力不大,用并行处理进一步提速:$allComputers | ForEach-Object -Parallel { $pdc = $using:pdc $computer = Get-ADComputer -Identity $_.Name -Properties lastLogon -Server $pdc [PSCustomObject]@{ Name = $computer.Name LastLogon = [DateTime]::FromFileTime($computer.lastLogon) QueryDC = $pdc } } -ThrottleLimit 50
这样改完,3000台客户端的查询时间应该能压缩到15-30分钟,和AD Tidy差不多。
内容的提问来源于stack exchange,提问作者Asharon
相关产品推荐
相关产品推荐

