PowerShell批量创建AD用户脚本故障排查求助
批量创建AD用户脚本问题排查与修复
问题概述
编写PowerShell脚本实现从CSV批量创建AD用户、生成随机密码并发送结果邮件,但运行异常:
- CSV中5个测试用户仅创建第一个,且缺少名、显示名,未加入指定组,账户处于禁用状态;
- 发送的邮件仅包含报错信息,未显示已创建用户;
- 担忧密码重复,需确保每个用户密码唯一。
运行报错:
Get-ADUser : Cannot find an object with identity: 'ScriptTestUser001' under: 'DC=mydc'Get-ADGroup : Cannot find an object with identity: 'Group1, Group2' under: 'DC=mydc'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
相关产品推荐
相关产品推荐

