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

PowerShell批量创建AD用户脚本故障排查求助

批量创建AD用户脚本问题排查与修复

问题概述

编写PowerShell脚本实现从CSV批量创建AD用户、生成随机密码并发送结果邮件,但运行异常:

  • CSV中5个测试用户仅创建第一个,且缺少名、显示名,未加入指定组,账户处于禁用状态;
  • 发送的邮件仅包含报错信息,未显示已创建用户;
  • 担忧密码重复,需确保每个用户密码唯一。

运行报错:

  1. Get-ADUser : Cannot find an object with identity: 'ScriptTestUser001' under: 'DC=mydc'
  2. Get-ADGroup : Cannot find an object with identity: 'Group1, Group2' under: 'DC=mydc'
  3. Cannot overwrite variable Error because it is read-only or constant.

用户原脚本:

$filePath = “D:\myfilepath\ScriptTestUsers.csv”

# Import the CSV file containing the user information
$users = Import-Csv $filePath

# Create an empty array to store the created users with their passwords
$createdUsers = @()

# Create an empty array to store the users that couldn't be created and the errors
$errorUsers = @()

# Loop through each user in the CSV file
foreach ($user in $users) {
    $firstname = $user.'FirstName' # Get the firstname from the CSV file
    $lastname = $user.'LastName' # Get the lastname from the CSV file
    $username = $user.'UserName' # Get the username from the CSV file

    # Check if the 'UserName' field is empty, if so, add the user to the error array and continue to the next iteration
    if (!$username) {
        $error = "Missing 'UserName' field for a user in the CSV file, skipping."
        $errorUsers += "$username $error"
        continue
    }

    # Check if the user already exists in AD, if so, add the user to the error array and continue to the next iteration
    if (Get-ADUser -Identity $username -ErrorAction SilentlyContinue) {
        $error = "User $username already exists in AD, skipping."
        $errorUsers += "$username $error"
        continue
    }

    $ou = $user.'OU' # Get the OU from the CSV file
    # Check if the specified OU exists, if not, add the user to the error array and continue to the next iteration
    if (!(Get-ADOrganizationalUnit -Identity $ou -ErrorAction SilentlyContinue)) {
        $error = "OU $ou does not exist, skipping."
        $errorUsers += "$username $error"
        continue
    }

    $groups = $user.'Groups' # Get the groups from the CSV file

    # Check if the specified group(s) exists, if not, add the user to the error array and continue to the next iteration
    if ($groups) {
        $missingGroups = $groups | Where-Object { !(Get-ADGroup -Identity $_ -ErrorAction SilentlyContinue) }
        if ($missingGroups) {
            $error = "Group(s) $missingGroups do not exist, skipping."
            $errorUsers += "$username $error"
            continue
        }
    }

    $expiry = $user.'ExpiryDate' # Get the account expiry date from the CSV file
    $description = $user.'Description' # Get the description from the CSV file

    # Generate a random password
    $password = [System.Web.Security.Membership]::GeneratePassword(16, 2)
    #$email = "<myemail@email.com>"
     # Create the AD user and add them to the specified groups
    try {
        New-ADUser -Name $firstname -Surname $lastname -SamAccountName $username -UserPrincipalName $username -Path $ou -Description $description -AccountExpirationDate $expiry -PassThru | Set-ADAccountPassword -Reset -NewPassword (ConvertTo-SecureString $password -AsPlainText -Force)
        if ($groups) {
            Add-ADGroupMember -Identity $groups -Members $username -ErrorAction Stop
        }
        # Add the user and their password to the array of created users
        $createdUsers += "$username $password"
    } catch {
        $error = $_.Exception.Message       
        $errorUsers += "$username $error"
    }
}


# Create the HTML body of the email with CSS styling
$body = "<html><head><style>body { background-color: lightblue; font-family: calibri;}</style></head><body>Successfully Created Users:<br>" + ($createdUsers -join "<br>") + "<br><br>Users that couldn't be created and the errors:<br>" + ($errorUsers -join "<br>") + "</body></html>"

# Send the email with the list of created users and their passwords and attach the original CSV file


$DateSh = (Get-Date).ToString("yyyyMMdd")

#Email options
$options = @{
    'SmtpServer' = "relay" 
    'To' = "<myemail@email.com>"
    'From' = "SERVER1 <server1@domain>" 
    'Subject' = "$DateSh-NewUsersCreated" 
    'BodyAsHtml' = $true
    'Attachments' = $filePath  
}
#Send email
Send-MailMessage @options -Body $Body

报错与功能问题修复

1. 修复只读变量Error赋值报错

$error是PowerShell内置只读变量,不能自定义赋值。将所有自定义错误存储变量改为$errMsg,示例:

# 替换原代码中所有自定义$error变量
if (!$username) {
    $errMsg = "Missing 'UserName' field for a user in the CSV file, skipping."
    $errorUsers += "$username $errMsg"
    continue
}

2. 修复组处理逻辑错误

CSV中Groups字段为逗号分隔字符串(如Group1, Group2),直接传入Get-ADGroup会被当作单个组名导致查找失败。需先拆分为数组:

# 拆分组字符串为数组并过滤空值
$groups = $user.'Groups' -split ',\s*' | Where-Object { $_ }

# 检查组是否存在的逻辑修改
if ($groups) {
    $missingGroups = @()
    foreach ($group in $groups) {
        if (!(Get-ADGroup -Identity $group -ErrorAction SilentlyContinue)) {
            $missingGroups += $group
        }
    }
    if ($missingGroups) {
        $errMsg = "Group(s) $($missingGroups -join ', ') do not exist, skipping."
        $errorUsers += "$username $errMsg"
        continue
    }
}

# 添加用户到组的逻辑修改
if ($groups) {
    foreach ($group in $groups) {
        Add-ADGroupMember -Identity $group -Members $username -ErrorAction Stop
    }
}

3. 修复AD用户创建参数错误

  • 默认创建的AD账户为禁用状态,需添加-Enabled $true参数;
  • -Name参数需传入全名(如"$firstname $lastname"),否则显示名异常;
  • 补充-GivenName设置名、-DisplayName设置显示名;
  • -UserPrincipalName需传入完整UPN(如"$username@mydc.com"):
New-ADUser -Name "$firstname $lastname" `
           -GivenName $firstname `
           -Surname $lastname `
           -SamAccountName $username `
           -UserPrincipalName "$username@mydc.com" ` # 替换为你的域名
           -Path $ou `
           -Description $description `
           -AccountExpirationDate $expiry `
           -Enabled $true `
           -PassThru | 
           Set-ADAccountPassword -Reset -NewPassword (ConvertTo-SecureString $password -AsPlainText -Force)

4. 确保密码唯一性

GeneratePassword生成重复密码的概率极低,若需进一步确保,可添加重复检查逻辑:

do {
    $password = [System.Web.Security.Membership]::GeneratePassword(16, 2)
    # 检查密码是否已在已创建用户列表中存在
    $isDuplicate = $createdUsers | Where-Object { $_ -match "\s$password$" }
} while ($isDuplicate)

5. 修复邮件内容展示问题

优化HTML邮件格式,用表格展示已创建用户,避免内容混乱:

# 构建已创建用户表格
$createdTable = @"
<table border="1">
    <tr>
        <th>用户名</th>
        <th>密码</th>
    </tr>
"@
foreach ($item in $createdUsers) {
    $user, $pwd = $item -split ' ', 2
    $createdTable += "<tr><td>$user</td><td>$pwd</td></tr>"
}
$createdTable += "</table>"

# 构建错误信息列表
$errorList = ($errorUsers | ForEach-Object { "<p>$_</p>" }) -join ''

# 最终HTML邮件内容
$body = @"
<html>
<head>
<style>
body { background-color: lightblue; font-family: calibri;}
table { border-collapse: collapse; margin: 10px 0;}
th, td { padding: 8px; text-align: left;}
th { background-color: #f2f2f2;}
</style>
</head>
<body>
<h3>成功创建的用户:</h3>
$($createdUsers.Count -gt 0 ? $createdTable : "<p>无</p>")
<h3>创建失败的用户及错误:</h3>
$($errorUsers.Count -gt 0 ? $errorList : "<p>无</p>")
</body>
</html>
"@

完整修复后的脚本

$filePath = "D:\myfilepath\ScriptTestUsers.csv" # 确保使用英文引号
$domainSuffix = "@mydc.com" # 替换为你的实际域名

# 导入CSV用户信息
$users = Import-Csv $filePath

# 初始化结果数组
$createdUsers = @()
$errorUsers = @()

foreach ($user in $users) {
    $firstname = $user.'FirstName'
    $lastname = $user.'LastName'
    $username = $user.'UserName'

    # 检查用户名是否为空
    if (!$username) {
        $errMsg = "Missing 'UserName' field, skipping."
        $errorUsers += "$username $errMsg"
        continue
    }

    # 检查用户是否已存在
    if (Get-ADUser -Identity $username -ErrorAction SilentlyContinue) {
        $errMsg = "User already exists in AD, skipping."
        $errorUsers += "$username $errMsg"
        continue
    }

    $ou = $user.'OU'
    # 检查OU是否存在
    if (!(Get-ADOrganizationalUnit -Identity $ou -ErrorAction SilentlyContinue)) {
        $errMsg = "OU does not exist, skipping."
        $errorUsers += "$username $errMsg"
        continue
    }

    # 处理组信息
    $groups = $user.'Groups' -split ',\s*' | Where-Object { $_ }
    if ($groups) {
        $missingGroups = @()
        foreach ($group in $groups) {
            if (!(Get-ADGroup -Identity $group -ErrorAction SilentlyContinue)) {
                $missingGroups += $group
            }
        }
        if ($missingGroups) {
            $errMsg = "Group(s) $($missingGroups -join ', ') do not exist, skipping."
            $errorUsers += "$username $errMsg"
            continue
        }
    }

    $expiry = $user.'ExpiryDate'
    $description = $user.'Description'

    # 生成唯一随机密码
    do {
        $password = [System.Web.Security.Membership]::GeneratePassword(16, 2)
        $isDuplicate = $createdUsers | Where-Object { $_ -match "\s$password$" }
    } while ($isDuplicate)

    try {
        # 创建AD用户
        New-ADUser -Name "$firstname $lastname" `
                   -GivenName $firstname `
                   -Surname $lastname `
                   -SamAccountName $username `
                   -UserPrincipalName "$username$domainSuffix" `
                   -Path $ou `
                   -Description $description `
                   -AccountExpirationDate $expiry `
                   -Enabled $true `
                   -PassThru | 
                   Set-ADAccountPassword -Reset -NewPassword (ConvertTo-SecureString $password -AsPlainText -Force)

        # 添加用户到指定组
        if ($groups) {
            foreach ($group in $groups) {
                Add-ADGroupMember -Identity $group -Members $username -ErrorAction Stop
            }
        }

        $createdUsers += "$username $password"
    } catch {
        $errMsg = $_.Exception.Message       
        $errorUsers += "$username $errMsg"
    }
}

# 构建邮件内容
$createdTable = @"
<table border="1">
    <tr>
        <th>用户名</th>
        <th>密码</th>
    </tr>
"@
foreach ($item in $createdUsers) {
    $user, $pwd = $item -split ' ', 2
    $createdTable += "<tr><td>$user</td><td>$pwd</td></tr>"
}
$createdTable += "</table>"

$errorList = ($errorUsers | ForEach-Object { "<p>$_</p>" }) -join ''

$body = @"
<html>
<head>
<style>
body { background-color: lightblue; font-family: calibri;}
table { border-collapse: collapse; margin: 10px 0;}
th, td { padding: 8px; text-align: left;}
th { background-color: #f2f2f2;}
</style>
</head>
<body>
<h3>成功创建的用户:</h3>
$($createdUsers.Count -gt 0 ? $createdTable : "<p>无</p>")
<h3>创建失败的用户及错误:</h3>
$($errorUsers.Count -gt 0 ? $errorList : "<p>无</p>")
</body>
</html>
"@

# 发送邮件
$DateSh = (Get-Date).ToString("yyyyMMdd")
$options = @{
    'SmtpServer' = "relay" 
    'To' = "<myemail@email.com>"
    'From' = "SERVER1 <server1@domain>" 
    'Subject' = "$DateSh-NewUsersCreated" 
    'BodyAsHtml' = $true
    'Attachments' = $filePath  
}
Send-MailMessage @options -Body $Body

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 03:21:08