You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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”

出现负数的原因有两点:

  1. 变量$ahora未定义,导致时间计算逻辑异常;
  2. 时间差计算方式错误,且域密码最大有效期$intMaxPwdAge未正确获取。

修复方案

  1. 定义当前时间变量:在脚本开头添加$ahora = Get-Date;
  2. 正确获取域密码最大有效期:从域根节点读取maxPwdAge属性(该属性存储的是负数时间戳,需转换为正数天数);
  3. 修正时间差计算逻辑:使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 17:22:21