基于日期时间的PowerShell AD过滤:Get-ADUser的LDAP筛选问题
解决方案
方法1:直接修改现有LDAP筛选规则(推荐,兼容性最好)
你只需要提前把30天前的时间转换为AD存储账户过期时间用的Windows文件时间格式,直接嵌入筛选字符串即可,修改后的完整代码如下:
# 定义过期30天的阈值,转换为文件时间格式 $expireThreshold = (Get-Date).AddDays(-30).ToFileTime() $filterString = " (& (AccountExpires>=1) (AccountExpires<=$expireThreshold) (!(UserAccountControl:1.2.840.113556.1.4.803:=2)) )" -replace "`r`n", "" $UsersToDisable = Get-ADUser -LDAPFilter $filterString -Properties AccountExpirationDate if($null -ne $UsersToDisable) { Write-Output "`n以下用户账户已过期超过30天,将被禁用并移动到禁用OU:" foreach ($user in $UsersToDisable){ $user | Select UserPrincipalName, AccountExpirationDate | Write-Output # 生产环境执行前先注释以下两行,确认筛选结果符合预期再放开 # $user | Disable-ADAccount # $user | Move-ADObject -TargetPath "OU=Disabled Users,DC=domain,DC=local" } }
改动说明
- 提前将30天阈值转成了文件时间格式,直接替换原筛选规则里的当前时间变量即可,LDAP筛选直接支持数值比较,不需要额外格式转换
- 提前在
Get-ADUser时就拉取AccountExpirationDate属性,避免循环内重复查询AD,大幅提升执行效率 - 把
$UsersToDisable -ne $null改成$null -ne $UsersToDisable,是PowerShell比较的标准写法,避免变量为集合时逻辑判断出错
方法2:使用PowerShell原生-Filter参数实现位运算
如果你更习惯用-Filter参数,也可以通过band位与运算符实现位筛选,不需要写LDAP格式的位规则,写法如下:
$expireThreshold = (Get-Date).AddDays(-30) $UsersToDisable = Get-ADUser -Filter { AccountExpirationDate -lt $expireThreshold -and AccountExpires -ge 1 -and -not (UserAccountControl -band 2) } -Properties AccountExpirationDate # 后续遍历禁用、移动用户的逻辑和方法1完全一致
说明
- PowerShell的AD模块Filter参数原生支持
band位与运算符,UserAccountControl -band 2就可以匹配已禁用的账户,取反就是筛选未禁用的用户 - 这里直接用DateTime类型的
AccountExpirationDate做时间比较,不需要手动转文件时间,AD模块会自动完成格式转换
内容的提问来源于stack exchange,提问作者Daryl Titcomb
相关产品推荐
相关产品推荐

