PowerShell AD密码过期通知脚本报错及数值异常求助
Active Directory密码过期通知脚本问题修复
问题1:PasswordLastChanged引发的空引用错误
错误核心是部分用户对象的PasswordLastChanged属性为null,直接强制转换为[datetime]会触发异常。这类情况常见于从未设置过密码的新用户或密码属性未初始化的账户。
修复方案
替换原脚本中[datetime]$PasswordLastChanged = $theuser.PasswordLastChanged这一行,改用AD原生存储密码修改时间的pwdLastSet属性,先判断属性是否存在再处理:
$pwdLastSet = $theuser.Properties['pwdLastSet'].Value if ($pwdLastSet -eq $null) { # 密码从未设置,直接标记为过期 $strExpiringDays = "CADUCADA" $avisar = 0 continue # 跳过后续计算逻辑 } # 将AD存储的文件时间戳转换为DateTime格式 [datetime]$PasswordLastChanged = [DateTime]::FromFileTime($pwdLastSet)
问题2:显示-67而非“CADUCADA”
出现负数的原因有两点:
- 变量
$ahora未定义,导致时间计算逻辑异常; - 时间差计算方式错误,且域密码最大有效期
$intMaxPwdAge未正确获取。
修复方案
- 定义当前时间变量:在脚本开头添加
$ahora = Get-Date; - 正确获取域密码最大有效期:从域根节点读取
maxPwdAge属性(该属性存储的是负数时间戳,需转换为正数天数); - 修正时间差计算逻辑:使用
TotalDays而非Days,确保计算的是完整天数差。
整合后的关键代码片段:
# 提前获取域密码最大有效期 $domain = [ADSI]"LDAP://RootDSE" $maxPwdAgeEntry = [ADSI]"LDAP://$($domain.defaultNamingContext)" $intMaxPwdAge = [int]([TimeSpan]::FromTicks($maxPwdAgeEntry.maxPwdAge.Value.Ticks * -1)).TotalDays $ahora = Get-Date # 循环内的时间计算部分 $timeSpan = $ahora - $PasswordLastChanged $intTimeInterval = [int]$timeSpan.TotalDays if ($intTimeInterval -ge $intMaxPwdAge) { $strExpiringDays = "CADUCADA" $avisar = 0 } else { $ExpiringDate = $PasswordLastChanged.AddDays($intMaxPwdAge) $fechacaducidad = $Expiringdate.ToString("dd/MM/yyyy") $ExpiringDays = [int]($ExpiringDate - $ahora).TotalDays $strExpiringDays = "$ExpiringDays dias" }
完整修改后的脚本
# 获取域密码最大有效期 $domain = [ADSI]"LDAP://RootDSE" $maxPwdAgeEntry = [ADSI]"LDAP://$($domain.defaultNamingContext)" $intMaxPwdAge = [int]([TimeSpan]::FromTicks($maxPwdAgeEntry.maxPwdAge.Value.Ticks * -1)).TotalDays $ahora = Get-Date $searcher = New-Object DirectoryServices.DirectorySearcher([adsi]"") $searcher.filter = "(&(objectclass=user)(objectcategory=person)(mail=*)(!userAccountControl:1.2.840.113556.1.4.803:=2))" $users = $searcher.findall() Foreach ($user in $users) { $TheUser = $user.GetDirectoryEntry() $usuario = $theuser.samaccountname $nombre = $theuser.givenname $apellidos = $theuser.sn $mail = $theuser.mail $uac = $theUser.userAccountControl $flags = Get-Uac("$uac") if ($flags -notcontains "DONT_EXPIRE_PASSWORD") { $pwdLastSet = $theuser.Properties['pwdLastSet'].Value if ($pwdLastSet -eq $null) { $strExpiringDays = "CADUCADA" $avisar = 0 continue } [datetime]$PasswordLastChanged = [DateTime]::FromFileTime($pwdLastSet) $timeSpan = $ahora - $PasswordLastChanged $intTimeInterval = [int]$timeSpan.TotalDays if ($intTimeInterval -ge $intMaxPwdAge) { $strExpiringDays = "CADUCADA" $avisar = 0 } else { $ExpiringDate = $PasswordLastChanged.AddDays($intMaxPwdAge) $fechacaducidad = $Expiringdate.ToString("dd/MM/yyyy") $ExpiringDays = [int]($ExpiringDate - $ahora).TotalDays $strExpiringDays = "$ExpiringDays dias" } } }
内容的提问来源于stack exchange,提问作者Alejandro Silva
相关产品推荐
相关产品推荐

