PowerShell脚本问题:筛选指定OU有姓氏用户并添加至邮件安全组
问题描述
四天前我发布的问题得到社区热心帮助,现在已经能筛选特定父OU中有姓氏的用户。下一步需要把这些位于指定父OU、有姓氏的启用用户添加至邮件启用安全组。我参考资料写了脚本,但脚本仍会遍历子OU,还会添加无姓氏用户,肯定哪里错了。
原脚本如下:
$Admin_Accounts = 'OU=Administrators,OU=Company,DC=CompanyDC,DC=local' $Service_Accounts = 'OU=Administrators,OU=Company,DC=CompanyDC,DC=local' $Disabled = 'OU=Administrators,OU=Company,DC=CompanyDC,DC=local' $Test_PowerPoint_GPO = 'OU=Administrators,OU=Company,DC=CompanyDC,DC=local' $Exclude = '({0}|{1}|{2})$' -f \[regex\]::Escape($Admin_Accounts), \[regex\]::Escape($Service_Accounts), \[regex\]::Escape($Disabled), \[regex\]::Escape($Test_PowerPoint_GPO) Get-ADUser -Filter 'Enabled -eq $true' -SearchBase 'OU=Users,OU=Company,DC=CompanyDC,DC=local' | Where-Object { !\[string\]::IsNullOrWhiteSpace($_.Surname) -and $_.DistinguishedName -notmatch $Exclude } | Select-Object SamAccountName $TargetGroup = “Company Team“ $TargetOU = “OU=Users,OU=Company,DC=Company,DC=local“ $Exclude = '({0}|{1}|{2})$' -f \[regex\]::Escape($Admin_Accounts), \[regex\]::Escape($Service_Accounts), \[regex\]::Escape($Disabled), \[regex\]::Escape($Test_PowerPoint_GPO) $UserAccounts = Get-ADUser -Filter 'Enabled -eq $true' | ?{$_.DistinguishedName -like “_*$TargetOU*” -and $.Enabled -eq “True”} Where-Object { !\[string\]::IsNullOrWhiteSpace($_.Surname) -and $_.DistinguishedName -notmatch $Exclude } | Select-Object SamAccountName ForEach($User in $UserAccounts) { $UsersName = $User.Name \#Check for group membership $Membership = Get-ADGroup $TargetGroup | Get-ADGroupMember | ?{$\_.Name -eq $UsersName} if(!$Membership) { “Adding $UsersName to $TargetGroup” Get-ADGroup $TargetGroup | Add-ADGroupMember -Members $User -Verbose } }
错误分析与修正方案
原脚本的核心问题:
- 第二个
Get-ADUser未指定-SearchBase和-SearchScope,导致遍历整个AD目录,用-like判断OU既低效又容易匹配错误 - 管道语法错误:
Where-Object没有正确衔接前面的$UserAccounts赋值语句,导致筛选逻辑失效 - 判断组会员的方式效率极低:
Get-ADGroupMember会拉取组内所有成员,循环判断每个用户完全没必要 - 重复定义
$Exclude变量,冗余且易出错 - 语法细节错误:使用中文引号(“”)、变量名漏写下划线(
$.Enabled应为$_.Enabled)、正则构建时多写了转义反斜杠
修正后的脚本
# 定义需要排除的OU(注意:原脚本中所有排除OU都写的同一个,实际使用时请替换为真实OU路径) $Admin_Accounts = 'OU=Administrators,OU=Company,DC=CompanyDC,DC=local' $Service_Accounts = 'OU=Administrators,OU=Company,DC=CompanyDC,DC=local' $Disabled_OU = 'OU=Administrators,OU=Company,DC=CompanyDC,DC=local' $Test_PowerPoint_GPO = 'OU=Administrators,OU=Company,DC=CompanyDC,DC=local' # 构建排除OU的正则表达式(匹配用户DistinguishedName的结尾) $ExcludeOUsPattern = '({0}|{1}|{2}|{3})$' -f [regex]::Escape($Admin_Accounts), [regex]::Escape($Service_Accounts), [regex]::Escape($Disabled_OU), [regex]::Escape($Test_PowerPoint_GPO) # 配置目标组和目标OU $TargetGroup = "Company Team" $TargetOU = "OU=Users,OU=Company,DC=Company,DC=local" # 获取符合条件的用户:指定父OU下(仅当前OU,不遍历子OU)、启用状态、存在姓氏、不在排除OU内 $QualifiedUsers = Get-ADUser -Filter { Enabled -eq $true -and Surname -ne "$null" } ` -SearchBase $TargetOU ` -SearchScope OneLevel ` | Where-Object { $_.DistinguishedName -notmatch $ExcludeOUsPattern } # 提前获取目标组的所有成员DN,提升判断效率 $GroupMemberDNs = (Get-ADGroup $TargetGroup -Properties Members).Members # 批量处理用户添加 foreach ($User in $QualifiedUsers) { if ($GroupMemberDNs -notcontains $User.DistinguishedName) { Write-Host "添加 $($User.Name) 到 $TargetGroup" Add-ADGroupMember -Identity $TargetGroup -Members $User -Verbose } }
关键改进说明:
- 精准筛选用户:用
Get-ADUser的-Filter直接筛选启用且有姓氏的用户,比后续Where-Object更高效,减少不必要的数据传输 - 限制OU遍历范围:添加
-SearchScope OneLevel,只遍历指定的父OU,不会递归子OU - 高效判断组会员:提前一次获取组内所有成员的
DistinguishedName,用-notcontains快速判断,避免重复调用AD命令 - 修复语法错误:统一使用英文引号,修正变量名错误,移除多余的转义字符
- 精简代码结构:合并重复变量定义,逻辑更清晰
内容的提问来源于stack exchange,提问作者Smoore
相关产品推荐
相关产品推荐

