PowerShell跨域校验AD密码同步时报字符串无法识别为有效DateTime错误
报错根因
- 循环逻辑错误:
foreach遍历用户集合时,内部两次AD查询都使用了通配符过滤条件UserPrincipalName -like '$UPN',每次查询都会返回域内所有匹配后缀的用户集合,而非当前循环对应的单个用户。此时直接读取.passwordlastset属性,PowerShell会将集合内所有用户的该属性值拼接为一整段长字符串(即报错信息中包含多组时间的字符串内容),自然无法被识别为合法的单DateTime类型。 - 执行顺序错误:先执行
New-TimeSpan计算时间差,再判断两个时间值是否为空,只要任意一个值为$null就会触发类型转换报错。 - 时间差判断逻辑缺陷:仅用
$Difference.Minutes取差值的分钟部分,会漏判超过1小时的时间差(例如差1小时7分钟时,Minutes属性值仅为7,无法体现小时级的偏移)。 - 冗余查询:首次拉取域1用户列表时没有读取
passwordlastset属性,循环内重复查询域1全量匹配用户,执行效率极低。
修正后代码
$UPNSuffix = "*contoso.com" # 拉取域1用户时直接返回需要的PasswordLastset属性,避免循环内重复查询 $Domain1Users = Get-ADUser -Filter "UserPrincipalName -like '$UPNSuffix'" -Properties PasswordLastset foreach ($User in $Domain1Users) { # 直接读取当前循环对象的域1密码时间 $PwdTimeDomain1 = $User.PasswordLastset # 域2查询时精确匹配当前用户的UPN,仅返回单个用户对象 $Domain2User = Get-ADUser -Server "DOMAIN.TWO.COM" -Filter "UserPrincipalName -eq '$($User.UserPrincipalName)'" -Properties PasswordLastset $PwdTimeDomain2 = $Domain2User.PasswordLastset # 先校验两个时间值非空,再计算差值 if ($null -ne $PwdTimeDomain1 -and $null -ne $PwdTimeDomain2) { $timeDiff = New-TimeSpan -Start $PwdTimeDomain2 -End $PwdTimeDomain1 # 取总分钟差的绝对值判断,兼容正负偏移,避免漏判长周期差值 if ([math]::Abs($timeDiff.TotalMinutes) -gt 5) { Write-Host "账号 $($User.UserPrincipalName) 密码未同步,两域密码设置时间差为 $([math]::Round($timeDiff.TotalMinutes,2)) 分钟" } } }
注意事项
- 如果两个域的同账号UPN不统一,可将域2查询的过滤条件替换为
SamAccountName -eq '$($User.SamAccountName)',按你实际环境的账号映射规则调整即可。 - 修正查询逻辑后,
PasswordLastset返回的是AD原生的DateTime类型值,不需要手动做字符串转时间的处理,不会再触发该类型转换报错。
内容的提问来源于stack exchange,提问作者Ralph
相关产品推荐
相关产品推荐

