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

ADSI验证异常?PowerShell批量创建AD OU与用户遇重复错误

问题分析与解决方案

首先看你遇到的错误:An attempt was made to add an object to the directory with a name that is already in use,这说明脚本在尝试创建已经存在的OU,而问题根源出在变量拼写错误和重复检查/创建OU的逻辑冗余上。

1. 核心问题:未定义的变量$iIntake

看你的代码里这段:

$UserOUParent = "OU=Year "+$iIntake+" Intake,OU=Students,OU=Users,OU=Roding,DC=Zulbag,DC=com"

你定义的变量是$Intake = $user.Intake,但这里写的是$iIntake(多了个i),这个变量从未赋值,默认是空字符串。这会导致:

  • 第一次循环时,$UserOUParent的路径变成OU=Year Intake,...(注意Year和Intake之间有两个空格),此时这个OU确实不存在,所以脚本会创建正确的父OU(因为创建时用的是$Intake)。
  • 第二次循环时,$iIntake依然是空,[ADSI]::Exists("LDAP://$UserOUParent")还是会返回false,脚本再次尝试创建父OU,但父OU已经存在,于是触发报错。

2. 优化后的修复代码

除了修正变量拼写,我们还可以优化逻辑:先收集所有需要创建的OU,去重后批量创建,避免每个用户循环都重复检查/创建OU,既提升效率也避免AD操作的竞争问题。

$ErrorActionPreference = "Stop"
Import-Module ActiveDirectory

# 导入CSV并提取所有需要的OU信息,去重
$CSV = Import-Csv "C:\Scripts\AddPupils.csv"
$requiredOUs = $CSV | ForEach-Object {
    [PSCustomObject]@{
        ParentOUName = "Year $($_.Intake) Intake"
        ParentOUPath = "OU=Students,OU=Users,OU=Roding,DC=Zulbag,DC=Com"
        ClassOUName = "Class $($_.YearClass.Substring(1,1))"
        ClassOUPath = "OU=Year $($_.Intake) Intake,OU=Students,OU=Users,OU=Roding,DC=Zulbag,DC=Com"
    }
} | Select-Object ParentOUName, ParentOUPath, ClassOUName, ClassOUPath -Unique

# 创建父OU(入学批次OU)
foreach ($ou in $requiredOUs) {
    $parentOUFullPath = "OU=$($ou.ParentOUName),$($ou.ParentOUPath)"
    if (-not (Get-ADOrganizationalUnit -Filter "Name -eq '$($ou.ParentOUName)'" -SearchBase $ou.ParentOUPath -SearchScope OneLevel -ErrorAction SilentlyContinue)) {
        Write-Output "Creating parent OU: $($ou.ParentOUName)"
        New-ADOrganizationalUnit -Name $ou.ParentOUName -Path $ou.ParentOUPath -ProtectedFromAccidentalDeletion $False
    }
}

# 创建班级OU
foreach ($ou in $requiredOUs) {
    $classOUFullPath = "OU=$($ou.ClassOUName),$($ou.ClassOUPath)"
    if (-not (Get-ADOrganizationalUnit -Filter "Name -eq '$($ou.ClassOUName)'" -SearchBase $ou.ClassOUPath -SearchScope OneLevel -ErrorAction SilentlyContinue)) {
        Write-Output "Creating class OU: $($ou.ClassOUName)"
        New-ADOrganizationalUnit -Name $ou.ClassOUName -Path $ou.ClassOUPath -ProtectedFromAccidentalDeletion $False
    }
}

# 处理用户创建和组操作
foreach ($user in $CSV) {
    $GivenName = $user.GivenName
    $SurName = $user.SurName
    $UserName = $user.UserName
    $Class = $user.YearClass
    $Intake = $user.Intake
    $DisplayName = "$GivenName $SurName"
    
    # 用户路径
    $userPath = "OU=Class $($Class.Substring(1,1)),OU=Year $Intake Intake,OU=Students,OU=Users,OU=Roding,DC=Zulbag,DC=Com"
    
    Write-Output "Creating user: $DisplayName"
    New-ADUser `
        -Name $DisplayName `
        -SurName $SurName `
        -GivenName $GivenName `
        -DisplayName $DisplayName `
        -SamAccountName $UserName `
        -UserPrincipalName "$UserName@Zulbag.com" `
        -AccountPassword (ConvertTo-SecureString "Testing123" -AsPlainText -force) `
        -CannotChangePassword $true `
        -ChangePasswordAtLogon $false `
        -PasswordNeverExpires $true `
        -EmailAddress "$UserName@Zulbag.com" `
        -Country "GB" `
        -Path $userPath `
        -ProfilePath "D:\Shares\User Accounts\Students\Intake Year $Intake\Class $($Class.Substring(1,1))\Profiles\$DisplayName" `
        -Enabled $true

    # 组操作部分同样修正变量并优化
    $groupName = "Redirection $($Intake.Substring(2,2))$($Class.Substring(1,1))"
    $groupOUName = "Intake $Intake"
    $groupOUPath = "OU=Folder Redirection Groups,OU=Security Groups,OU=Roding,DC=Zulbag,DC=Com"
    $fullGroupOUPath = "OU=$groupOUName,$groupOUPath"
    
    # 检查并创建组OU(如果需要)
    if (-not (Get-ADOrganizationalUnit -Filter "Name -eq '$groupOUName'" -SearchBase $groupOUPath -SearchScope OneLevel -ErrorAction SilentlyContinue)) {
        Write-Output "Creating group OU: $groupOUName"
        New-ADOrganizationalUnit -Name $groupOUName -Path $groupOUPath -ProtectedFromAccidentalDeletion $False
    }
    
    # 检查并创建组
    if (-not (Get-ADGroup -Filter "Name -eq '$groupName'" -SearchBase $fullGroupOUPath -SearchScope OneLevel -ErrorAction SilentlyContinue)) {
        Write-Output "Creating group: $groupName"
        New-ADGroup -Name $groupName -GroupScope "Global" -Path $fullGroupOUPath
    }
    
    # 添加用户到组
    Write-Output "Adding $UserName to group $groupName"
    Add-ADGroupMember -Identity $groupName -Members $UserName

    Start-Sleep -Seconds 1 # 缩短延迟,按需调整
}

pause

3. 关键优化点说明

  • 修正变量拼写:把所有$iIntake替换为$Intake,确保路径正确。
  • 去重OU创建:先收集所有需要的OU,去重后再批量创建,避免每个用户循环都重复执行相同的OU检查/创建操作。
  • 改用Get-ADOrganizationalUnit检查OU:相比[ADSI]::Exists,这个方法更可靠,不会因为LDAP路径拼写错误或AD缓存导致误判,同时可以精准指定搜索范围。
  • 组操作逻辑同步优化:同样修正变量并提前检查组OU和组的存在性,避免重复创建。

4. 额外建议

  • 如果你的AD环境有多域控制器,可能需要考虑AD复制延迟问题,可以在创建OU后添加短暂延迟,或者指定操作的域控制器(用-Server参数)。
  • 建议把密码等敏感信息放在变量或配置文件中,不要硬编码在脚本里。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:29:56