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

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
    }
}

关键改进说明:

  1. 精准筛选用户:用Get-ADUser的-Filter直接筛选启用且有姓氏的用户,比后续Where-Object更高效,减少不必要的数据传输
  2. 限制OU遍历范围:添加-SearchScope OneLevel,只遍历指定的父OU,不会递归子OU
  3. 高效判断组会员:提前一次获取组内所有成员的DistinguishedName,用-notcontains快速判断,避免重复调用AD命令
  4. 修复语法错误:统一使用英文引号,修正变量名错误,移除多余的转义字符
  5. 精简代码结构:合并重复变量定义,逻辑更清晰

内容的提问来源于stack exchange,提问作者Smoore

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 04:55:17