PowerShell 7并行ForEach-Object循环中无法存储AD对象至变量的问题
解决PowerShell并行获取AD LastLogon时的"invalid enumeration context"错误
问题根源
这个错误的核心原因是:你通过$using:DCs传递的ADDomainController对象,其内部的AD连接上下文并非线程安全。在并行线程中复用这些对象时,会导致AD服务器返回枚举上下文无效的错误。另外,直接在并行循环中反复复用同一个DC对象查询,也容易触发这类连接上下文冲突。
修复方案
核心修改点
- 不要传递
ADDomainController对象,改为传递DC的名称字符串,让每个并行线程创建独立的AD连接上下文。 - 优化查询逻辑,增加错误处理,避免单个DC查询失败中断整个用户的处理流程。
修改后的代码
$users = Get-ADUser -Filter "[filter]" # 提取DC名称字符串,而非传递ADDomainController对象 $DCNames = (Get-ADDomainController -Filter * | Where-Object { $_.Site -in $using:sites }).Name $users | ForEach-Object -ThrottleLimit 2 -Parallel { $dcList = $using:DCNames $currentUser = $_ # 遍历所有DC查询该用户的LastLogon $lastLogonRecords = foreach ($dcName in $dcList) { try { $lastLogonAD = Get-ADUser -Identity $currentUser -Properties LastLogon -Server $dcName -ErrorAction Stop | Select-Object -ExpandProperty LastLogon # 过滤掉未登录的记录(LastLogon值为0) if ($lastLogonAD -ne 0) { [PSCustomObject]@{ UserName = $currentUser.SamAccountName DC = $dcName LastLogon = [datetime]::FromFileTimeUTC($lastLogonAD) } } } catch { Write-Warning "用户 $($currentUser.SamAccountName) 查询DC $dcName 失败: $_" continue } } # 输出该用户的最新LastLogon记录(因为LastLogon不跨DC同步,需取最大值) $lastLogonRecords | Sort-Object LastLogon -Descending | Select-Object -First 1 }
额外说明
- LastLogon属性特性:该属性是DC本地存储的,不会同步到其他域控制器,所以通常需要查询所有DC后取最大值作为用户的实际最后登录时间,代码中已包含此逻辑。
- ThrottleLimit调整:可以根据AD服务器的负载情况调整该值,避免过高的并行请求对AD造成压力。
- 错误处理:通过
try/catch捕获单个DC的查询错误,确保其他DC的查询不受影响。
内容的提问来源于stack exchange,提问作者swtto
相关产品推荐
相关产品推荐

