Resolved users not creating properly, fixed up script details
This commit is contained in:
parent
f5a40e296a
commit
798a19a36e
508
New-ADUser.ps1
508
New-ADUser.ps1
@ -1,11 +1,17 @@
|
|||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Creates new AD users with email attributes and copy functionality.
|
Creates or copies AD users with complete error handling
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Enhanced version with mailNickname and proxyAddresses support.
|
A script that can create a new user account from scratch, or copy an existing user for their security groups.
|
||||||
|
Has built-in error tolerant handling and recommendations, will continue where possible and report any issues.
|
||||||
|
Script will automatically add 'mailnickname' and 'proxyAddresses' to attribute editor.
|
||||||
.NOTES
|
.NOTES
|
||||||
Version : 2.1
|
Author : Kyle Pope + AI
|
||||||
|
Created : 13/04/25
|
||||||
|
Version : 1.0.7
|
||||||
Requires : PowerShell with Active Directory module
|
Requires : PowerShell with Active Directory module
|
||||||
|
File Name : New-ADUser.ps1
|
||||||
|
|
||||||
#>
|
#>
|
||||||
|
|
||||||
# Import Active Directory module
|
# Import Active Directory module
|
||||||
@ -19,13 +25,13 @@ catch {
|
|||||||
|
|
||||||
function Show-Menu {
|
function Show-Menu {
|
||||||
param (
|
param (
|
||||||
[string]$Title = 'AD User Creation Options'
|
[string]$Title = 'AD User Management'
|
||||||
)
|
)
|
||||||
Clear-Host
|
Clear-Host
|
||||||
Write-Host "================ $Title ================"
|
Write-Host "================ $Title ================"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "1: Create a new user from scratch"
|
Write-Host "1: Create new user"
|
||||||
Write-Host "2: Copy settings from existing user"
|
Write-Host "2: Copy existing user"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "Q: Quit"
|
Write-Host "Q: Quit"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
@ -57,8 +63,7 @@ function Get-ValidPassword {
|
|||||||
do {
|
do {
|
||||||
$password = Read-Host "Enter password (min 8 chars, complex)" -AsSecureString
|
$password = Read-Host "Enter password (min 8 chars, complex)" -AsSecureString
|
||||||
$passwordText = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
|
$passwordText = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
|
||||||
[Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
|
[Runtime.InteropServices.Marshal]::SecureStringToBSTR($password))
|
||||||
)
|
|
||||||
|
|
||||||
if ($passwordText.Length -lt 8) {
|
if ($passwordText.Length -lt 8) {
|
||||||
Write-Host "Password must be at least 8 characters" -ForegroundColor Red
|
Write-Host "Password must be at least 8 characters" -ForegroundColor Red
|
||||||
@ -84,6 +89,103 @@ function Get-ValidPassword {
|
|||||||
return $password
|
return $password
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Test-ADUserExists {
|
||||||
|
param (
|
||||||
|
[string]$Username,
|
||||||
|
[int]$RetryCount = 3,
|
||||||
|
[int]$DelaySeconds = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
for ($i = 1; $i -le $RetryCount; $i++) {
|
||||||
|
try {
|
||||||
|
$user = Get-ADUser -Identity $Username -ErrorAction Stop
|
||||||
|
return $user
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
if ($i -lt $RetryCount) {
|
||||||
|
Write-Host "User not found yet, retrying in $DelaySeconds seconds... (Attempt $i of $RetryCount)" -ForegroundColor Yellow
|
||||||
|
Start-Sleep -Seconds $DelaySeconds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
function Set-UserEmailAttributes {
|
||||||
|
param (
|
||||||
|
[string]$Username,
|
||||||
|
[string]$EmailAddress,
|
||||||
|
[string]$Domain
|
||||||
|
)
|
||||||
|
|
||||||
|
$errors = @()
|
||||||
|
|
||||||
|
# Set mailNickname if available
|
||||||
|
try {
|
||||||
|
Set-ADUser -Identity $Username -Replace @{mailNickname=$Username} -ErrorAction Stop
|
||||||
|
Write-Host "Successfully set mailNickname: $Username" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$errors += "mailNickname: $($_.Exception.Message)"
|
||||||
|
Write-Host "Warning: Could not set mailNickname - $($_.Exception.Message)" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set proxyAddresses (primary SMTP address)
|
||||||
|
try {
|
||||||
|
$proxyAddress = "SMTP:$EmailAddress"
|
||||||
|
Set-ADUser -Identity $Username -Add @{proxyAddresses=$proxyAddress} -ErrorAction Stop
|
||||||
|
Write-Host "Successfully set proxyAddresses: $proxyAddress" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$errors += "proxyAddresses: $($_.Exception.Message)"
|
||||||
|
Write-Host "Warning: Could not set proxyAddresses - $($_.Exception.Message)" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
|
||||||
|
return $errors
|
||||||
|
}
|
||||||
|
|
||||||
|
function Show-FinalUserDetails {
|
||||||
|
param (
|
||||||
|
[string]$Username,
|
||||||
|
[array]$AttributeErrors
|
||||||
|
)
|
||||||
|
|
||||||
|
try {
|
||||||
|
$finalUser = Get-ADUser -Identity $Username -Properties * -ErrorAction SilentlyContinue
|
||||||
|
if ($finalUser) {
|
||||||
|
Write-Host "`nFinal User Details:" -ForegroundColor Cyan
|
||||||
|
$finalUser | Select-Object Name, SamAccountName, UserPrincipalName,
|
||||||
|
mailNickname, proxyAddresses, EmailAddress,
|
||||||
|
DistinguishedName, Enabled | Format-List
|
||||||
|
|
||||||
|
if ($AttributeErrors) {
|
||||||
|
Write-Host "`nAttribute Setting Errors:" -ForegroundColor Yellow
|
||||||
|
$AttributeErrors | ForEach-Object {
|
||||||
|
Write-Host " - $_" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host "`nNote: Could not retrieve final user details (replication in progress)" -ForegroundColor Yellow
|
||||||
|
if ($AttributeErrors) {
|
||||||
|
Write-Host "`nAttribute Setting Errors:" -ForegroundColor Yellow
|
||||||
|
$AttributeErrors | ForEach-Object {
|
||||||
|
Write-Host " - $_" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Host "`nNote: Could not retrieve complete user details - $($_.Exception.Message)" -ForegroundColor Yellow
|
||||||
|
if ($AttributeErrors) {
|
||||||
|
Write-Host "`nAttribute Setting Errors:" -ForegroundColor Yellow
|
||||||
|
$AttributeErrors | ForEach-Object {
|
||||||
|
Write-Host " - $_" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function CreateNewUser {
|
function CreateNewUser {
|
||||||
param (
|
param (
|
||||||
[string]$Domain
|
[string]$Domain
|
||||||
@ -103,12 +205,11 @@ function CreateNewUser {
|
|||||||
$ou = Read-Host "Enter OU distinguished name (e.g., OU=Users,DC=domain,DC=com) or leave blank for default"
|
$ou = Read-Host "Enter OU distinguished name (e.g., OU=Users,DC=domain,DC=com) or leave blank for default"
|
||||||
|
|
||||||
$password = Get-ValidPassword
|
$password = Get-ValidPassword
|
||||||
|
$emailAddress = "$username@$Domain"
|
||||||
|
$attributeErrors = @()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
# Build email attributes
|
# Base parameters
|
||||||
$emailAddress = "$username@$Domain"
|
|
||||||
|
|
||||||
# Base parameters that will always work
|
|
||||||
$newUserParams = @{
|
$newUserParams = @{
|
||||||
GivenName = $firstName
|
GivenName = $firstName
|
||||||
Surname = $lastName
|
Surname = $lastName
|
||||||
@ -123,139 +224,130 @@ function CreateNewUser {
|
|||||||
ErrorAction = 'Stop'
|
ErrorAction = 'Stop'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Set OU path
|
||||||
if (-not [string]::IsNullOrWhiteSpace($ou)) {
|
if (-not [string]::IsNullOrWhiteSpace($ou)) {
|
||||||
$newUserParams['Path'] = $ou
|
$newUserParams['Path'] = $ou
|
||||||
|
Write-Host "Creating user in specified OU: $ou" -ForegroundColor Cyan
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$newUserParams['Path'] = "CN=Users," + (Get-ADDomain).DistinguishedName
|
$defaultOU = "CN=Users," + (Get-ADDomain).DistinguishedName
|
||||||
}
|
$newUserParams['Path'] = $defaultOU
|
||||||
|
Write-Host "Using default Users container: $defaultOU" -ForegroundColor Cyan
|
||||||
# Try to add mailNickname if available (with error handling)
|
|
||||||
try {
|
|
||||||
$newUserParams['mailNickname'] = $username
|
|
||||||
Write-Host "Attempting to set mailNickname: $username" -ForegroundColor Cyan
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host "Warning: Could not set mailNickname attribute" -ForegroundColor Yellow
|
|
||||||
Write-Host "This attribute may not exist in your test environment" -ForegroundColor Yellow
|
|
||||||
Write-Host "User will be created without mailNickname (can be added later)" -ForegroundColor Yellow
|
|
||||||
}
|
|
||||||
|
|
||||||
# Try to add proxyAddresses if available (with error handling)
|
|
||||||
try {
|
|
||||||
$newUserParams['proxyAddresses'] = "SMTP:$emailAddress"
|
|
||||||
Write-Host "Attempting to set proxyAddresses: SMTP:$emailAddress" -ForegroundColor Cyan
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host "Warning: Could not set proxyAddresses attribute" -ForegroundColor Yellow
|
|
||||||
Write-Host "This attribute may not exist in your test environment" -ForegroundColor Yellow
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "`nCreating user with these confirmed attributes:" -ForegroundColor Cyan
|
|
||||||
$newUserParams.GetEnumerator() | Where-Object { $_.Key -ne 'AccountPassword' } | ForEach-Object {
|
|
||||||
Write-Host "$($_.Key): $($_.Value)"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Create the user
|
||||||
|
Write-Host "Creating user with basic attributes..." -ForegroundColor Cyan
|
||||||
New-ADUser @newUserParams
|
New-ADUser @newUserParams
|
||||||
Write-Host "User $username created successfully!" -ForegroundColor Green
|
|
||||||
|
|
||||||
# Clear the plaintext password from memory
|
# Verify creation with retry logic
|
||||||
|
$createdUser = Test-ADUserExists -Username $username
|
||||||
|
if (-not $createdUser) {
|
||||||
|
Write-Host "WARNING: Cannot verify user immediately (replication delay?)" -ForegroundColor Yellow
|
||||||
|
Write-Host "The user was created but may not be immediately visible." -ForegroundColor Yellow
|
||||||
|
Write-Host "Please check again in a few minutes." -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host "SUCCESS: User verified with DN: $($createdUser.DistinguishedName)" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set email attributes after creation
|
||||||
|
if ($username -and $emailAddress) {
|
||||||
|
Write-Host "`nSetting email attributes..." -ForegroundColor Cyan
|
||||||
|
$attributeErrors = Set-UserEmailAttributes -Username $username -EmailAddress $emailAddress -Domain $Domain
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show final details with any errors
|
||||||
|
Show-FinalUserDetails -Username $username -AttributeErrors $attributeErrors
|
||||||
|
|
||||||
|
# Clean up password
|
||||||
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR(
|
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR(
|
||||||
[Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
|
[Runtime.InteropServices.Marshal]::SecureStringToBSTR($password))
|
||||||
)
|
|
||||||
|
|
||||||
# Option to add to groups
|
# Group membership
|
||||||
$addGroups = Read-Host "Would you like to add the user to any groups? (Y/N)"
|
$addGroups = Read-Host "`nAdd user to groups? (Y/N)"
|
||||||
if ($addGroups -eq 'Y' -or $addGroups -eq 'y') {
|
if ($addGroups -eq 'Y' -or $addGroups -eq 'y') {
|
||||||
$groups = Read-Host "Enter group names (comma separated)"
|
$groups = Read-Host "Enter group names (comma separated)"
|
||||||
$groupArray = $groups -split ','
|
foreach ($group in ($groups -split ',').Trim()) {
|
||||||
|
|
||||||
foreach ($group in $groupArray) {
|
|
||||||
try {
|
try {
|
||||||
Add-ADGroupMember -Identity $group.Trim() -Members $username -ErrorAction Stop
|
Add-ADGroupMember -Identity $group -Members $username -ErrorAction Stop
|
||||||
Write-Host "Added to $group successfully." -ForegroundColor Green
|
Write-Host "Added to $group successfully" -ForegroundColor Green
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Write-Host "Error adding to group $group : $_" -ForegroundColor Red
|
Write-Host "Failed to add to $group : $_" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Write-Host "Error creating user: $($_.Exception.Message)" -ForegroundColor Red
|
Write-Host "ERROR: $($_.Exception.Message)" -ForegroundColor Red
|
||||||
|
|
||||||
if ($_.Exception.Message -like "*Access is denied*") {
|
if ($_.Exception.Message -like "*Access is denied*") {
|
||||||
Write-Host "`nTROUBLESHOOTING TIPS:" -ForegroundColor Yellow
|
Write-Host "`nTROUBLESHOOTING:" -ForegroundColor Yellow
|
||||||
Write-Host "1. Run PowerShell as Administrator" -ForegroundColor Yellow
|
Write-Host "1. Run as Administrator" -ForegroundColor Yellow
|
||||||
Write-Host "2. Verify you have permissions to create users in: $($newUserParams['Path'])" -ForegroundColor Yellow
|
Write-Host "2. Verify permissions on target OU" -ForegroundColor Yellow
|
||||||
Write-Host "3. Try a simpler OU path (e.g., CN=Users)" -ForegroundColor Yellow
|
Write-Host "3. Try simpler OU path" -ForegroundColor Yellow
|
||||||
}
|
|
||||||
elseif ($_.Exception.Message -like "*mailNickname*" -or $_.Exception.Message -like "*proxyAddresses*") {
|
|
||||||
Write-Host "`nNOTE: Some attributes not available in this environment" -ForegroundColor Yellow
|
|
||||||
Write-Host "The user was created successfully without these attributes" -ForegroundColor Green
|
|
||||||
Write-Host "You can add them later if needed" -ForegroundColor Yellow
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Write-Host "`nScript completed. Press Enter to continue..." -ForegroundColor Gray
|
||||||
|
$null = Read-Host
|
||||||
}
|
}
|
||||||
|
|
||||||
function Copy-ExistingUser {
|
function CopyExistingUser {
|
||||||
param (
|
param (
|
||||||
[string]$Domain
|
[string]$Domain
|
||||||
)
|
)
|
||||||
|
|
||||||
$sourceUsername = Read-Host "Enter username of the user you want to copy"
|
$sourceUsername = Read-Host "Enter username to copy"
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$sourceUser = Get-ADUser -Identity $sourceUsername -Properties * -ErrorAction Stop
|
$sourceUser = Get-ADUser -Identity $sourceUsername -Properties * -ErrorAction Stop
|
||||||
|
|
||||||
Write-Host "`nCopying settings from: $($sourceUser.Name)" -ForegroundColor Cyan
|
Write-Host "`nCopying from: $($sourceUser.Name)" -ForegroundColor Cyan
|
||||||
Write-Host "Current OU: $($sourceUser.DistinguishedName)`n" -ForegroundColor Cyan
|
Write-Host "Current location: $($sourceUser.DistinguishedName)" -ForegroundColor Cyan
|
||||||
|
|
||||||
# Get the parent OU from the source user's DN
|
# Get parent OU
|
||||||
$sourceOU = $sourceUser.DistinguishedName -replace '^CN=[^,]+,',''
|
$sourceOU = $sourceUser.DistinguishedName -replace '^CN=[^,]+,',''
|
||||||
Write-Host "Source user's OU: $sourceOU" -ForegroundColor Cyan
|
|
||||||
|
|
||||||
$firstName = Read-Host "Enter new user's first name [$($sourceUser.GivenName)]"
|
$firstName = Read-Host "First name [$($sourceUser.GivenName)]"
|
||||||
if ([string]::IsNullOrWhiteSpace($firstName)) { $firstName = $sourceUser.GivenName }
|
if ([string]::IsNullOrWhiteSpace($firstName)) { $firstName = $sourceUser.GivenName }
|
||||||
|
|
||||||
$lastName = Read-Host "Enter new user's last name [$($sourceUser.Surname)]"
|
$lastName = Read-Host "Last name [$($sourceUser.Surname)]"
|
||||||
if ([string]::IsNullOrWhiteSpace($lastName)) { $lastName = $sourceUser.Surname }
|
if ([string]::IsNullOrWhiteSpace($lastName)) { $lastName = $sourceUser.Surname }
|
||||||
|
|
||||||
$username = Read-Host "Enter new username (leave blank to auto-generate)"
|
$username = Read-Host "New username (blank to auto-generate)"
|
||||||
|
|
||||||
if ([string]::IsNullOrWhiteSpace($username)) {
|
if ([string]::IsNullOrWhiteSpace($username)) {
|
||||||
$username = ($firstName.Substring(0,1) + $lastName).ToLower()
|
$username = ($firstName.Substring(0,1) + $lastName).ToLower()
|
||||||
Write-Host "Auto-generated username: $username" -ForegroundColor Yellow
|
Write-Host "Auto-generated username: $username" -ForegroundColor Yellow
|
||||||
}
|
}
|
||||||
|
|
||||||
$displayName = "$firstName $lastName"
|
$displayName = "$firstName $lastName"
|
||||||
|
$emailAddress = "$username@$Domain"
|
||||||
|
$attributeErrors = @()
|
||||||
|
|
||||||
# Offer choice to use source OU or specify new one
|
# OU Selection
|
||||||
$ouChoice = Read-Host "Use same OU as source user? [$sourceOU] (Y/N)"
|
$ouChoice = Read-Host "Use source OU? [$sourceOU] (Y/N)"
|
||||||
if ($ouChoice -eq 'Y' -or $ouChoice -eq 'y') {
|
if ($ouChoice -eq 'Y' -or $ouChoice -eq 'y') {
|
||||||
$ou = $sourceOU
|
$ou = $sourceOU
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$ou = Read-Host "Enter new OU distinguished name (e.g., OU=Users,DC=domain,DC=com)"
|
$ou = Read-Host "Enter target OU DN"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Validate OU exists
|
# Validate OU
|
||||||
try {
|
try {
|
||||||
$null = Get-ADObject -Identity $ou -ErrorAction Stop
|
$null = Get-ADObject -Identity $ou -ErrorAction Stop
|
||||||
|
Write-Host "Validated target OU: $ou" -ForegroundColor Cyan
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Write-Host "Invalid OU specified: $ou" -ForegroundColor Red
|
Write-Host "Invalid OU, using source OU instead" -ForegroundColor Yellow
|
||||||
Write-Host "Defaulting to source user's OU: $sourceOU" -ForegroundColor Yellow
|
|
||||||
$ou = $sourceOU
|
$ou = $sourceOU
|
||||||
}
|
}
|
||||||
|
|
||||||
$password = Get-ValidPassword
|
$password = Get-ValidPassword
|
||||||
|
|
||||||
try {
|
try {
|
||||||
# Build fresh email attributes for new user
|
# Base parameters
|
||||||
$emailAddress = "$username@$Domain"
|
|
||||||
|
|
||||||
# Base parameters that will always work
|
|
||||||
$newUserParams = @{
|
$newUserParams = @{
|
||||||
GivenName = $firstName
|
GivenName = $firstName
|
||||||
Surname = $lastName
|
Surname = $lastName
|
||||||
@ -272,48 +364,45 @@ function Copy-ExistingUser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Copy organizational attributes if they exist
|
# Copy organizational attributes if they exist
|
||||||
if ($sourceUser.Company) { $newUserParams['Company'] = $sourceUser.Company }
|
$attributesToCopy = @('Company','Department','Title','Office',
|
||||||
if ($sourceUser.Department) { $newUserParams['Department'] = $sourceUser.Department }
|
'StreetAddress','City','State','PostalCode',
|
||||||
if ($sourceUser.Title) { $newUserParams['Title'] = $sourceUser.Title }
|
'Country','OfficePhone')
|
||||||
if ($sourceUser.Office) { $newUserParams['Office'] = $sourceUser.Office }
|
|
||||||
if ($sourceUser.StreetAddress) { $newUserParams['StreetAddress'] = $sourceUser.StreetAddress }
|
|
||||||
if ($sourceUser.City) { $newUserParams['City'] = $sourceUser.City }
|
|
||||||
if ($sourceUser.State) { $newUserParams['State'] = $sourceUser.State }
|
|
||||||
if ($sourceUser.PostalCode) { $newUserParams['PostalCode'] = $sourceUser.PostalCode }
|
|
||||||
if ($sourceUser.Country) { $newUserParams['Country'] = $sourceUser.Country }
|
|
||||||
if ($sourceUser.OfficePhone) { $newUserParams['OfficePhone'] = $sourceUser.OfficePhone }
|
|
||||||
|
|
||||||
# Try to add mailNickname if available
|
foreach ($attr in $attributesToCopy) {
|
||||||
try {
|
if ($sourceUser.$attr) {
|
||||||
$newUserParams['mailNickname'] = $username
|
$newUserParams[$attr] = $sourceUser.$attr
|
||||||
Write-Host "Attempting to set mailNickname: $username" -ForegroundColor Cyan
|
}
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host "Warning: Could not set mailNickname attribute" -ForegroundColor Yellow
|
|
||||||
}
|
|
||||||
|
|
||||||
# Try to add proxyAddresses if available
|
|
||||||
try {
|
|
||||||
$newUserParams['proxyAddresses'] = "SMTP:$emailAddress"
|
|
||||||
Write-Host "Attempting to set proxyAddresses: SMTP:$emailAddress" -ForegroundColor Cyan
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host "Warning: Could not set proxyAddresses attribute" -ForegroundColor Yellow
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "`nCreating user with these confirmed attributes:" -ForegroundColor Cyan
|
|
||||||
$newUserParams.GetEnumerator() | Where-Object { $_.Key -ne 'AccountPassword' } | ForEach-Object {
|
|
||||||
Write-Host "$($_.Key): $($_.Value)"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Write-Host "Creating user with basic attributes..." -ForegroundColor Cyan
|
||||||
New-ADUser @newUserParams
|
New-ADUser @newUserParams
|
||||||
Write-Host "User $username created successfully in $ou!" -ForegroundColor Green
|
|
||||||
|
|
||||||
|
# Verify creation with retry logic
|
||||||
|
$createdUser = Test-ADUserExists -Username $username
|
||||||
|
if (-not $createdUser) {
|
||||||
|
Write-Host "WARNING: Cannot verify user immediately (replication delay?)" -ForegroundColor Yellow
|
||||||
|
Write-Host "The user was created but may not be immediately visible." -ForegroundColor Yellow
|
||||||
|
Write-Host "Please check again in a few minutes." -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host "SUCCESS: User verified with DN: $($createdUser.DistinguishedName)" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set email attributes after creation
|
||||||
|
if ($username -and $emailAddress) {
|
||||||
|
Write-Host "`nSetting email attributes..." -ForegroundColor Cyan
|
||||||
|
$attributeErrors = Set-UserEmailAttributes -Username $username -EmailAddress $emailAddress -Domain $Domain
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show final details with any errors
|
||||||
|
Show-FinalUserDetails -Username $username -AttributeErrors $attributeErrors
|
||||||
|
|
||||||
|
# Clean up password
|
||||||
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR(
|
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR(
|
||||||
[Runtime.InteropServices.Marshal]::SecureStringToBSTR($password))
|
[Runtime.InteropServices.Marshal]::SecureStringToBSTR($password))
|
||||||
|
|
||||||
# Copy group memberships (excluding Domain Users)
|
# Copy groups
|
||||||
$copyGroups = Read-Host "Would you like to copy group memberships? (Y/N)"
|
$copyGroups = Read-Host "`nCopy group memberships? (Y/N)"
|
||||||
if ($copyGroups -eq 'Y' -or $copyGroups -eq 'y') {
|
if ($copyGroups -eq 'Y' -or $copyGroups -eq 'y') {
|
||||||
$groups = Get-ADPrincipalGroupMembership -Identity $sourceUsername |
|
$groups = Get-ADPrincipalGroupMembership -Identity $sourceUsername |
|
||||||
Where-Object { $_.Name -ne "Domain Users" }
|
Where-Object { $_.Name -ne "Domain Users" }
|
||||||
@ -322,200 +411,31 @@ function Copy-ExistingUser {
|
|||||||
foreach ($group in $groups) {
|
foreach ($group in $groups) {
|
||||||
try {
|
try {
|
||||||
Add-ADGroupMember -Identity $group -Members $username -ErrorAction Stop
|
Add-ADGroupMember -Identity $group -Members $username -ErrorAction Stop
|
||||||
Write-Host "Added to $($group.Name) successfully." -ForegroundColor Green
|
Write-Host "Added to $($group.Name)" -ForegroundColor Green
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Write-Host "Error adding to group $($group.Name) : $_" -ForegroundColor Red
|
Write-Host "Failed to add to $($group.Name) : $_" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Write-Host "No additional groups to copy." -ForegroundColor Yellow
|
Write-Host "No additional groups to copy" -ForegroundColor Yellow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Write-Host "Error creating user: $($_.Exception.Message)" -ForegroundColor Red
|
Write-Host "ERROR: $($_.Exception.Message)" -ForegroundColor Red
|
||||||
|
|
||||||
if ($_.Exception.Message -like "*parent is not on the list of possible superiors*") {
|
|
||||||
Write-Host "`nTROUBLESHOOTING TIPS:" -ForegroundColor Yellow
|
|
||||||
Write-Host "1. You don't have permission to create users in: $ou" -ForegroundColor Yellow
|
|
||||||
Write-Host "2. Try creating in the default Users container instead" -ForegroundColor Yellow
|
|
||||||
Write-Host "3. Run PowerShell as Domain Administrator" -ForegroundColor Yellow
|
|
||||||
}
|
|
||||||
elseif ($_.Exception.Message -like "*mailNickname*" -or $_.Exception.Message -like "*proxyAddresses*") {
|
|
||||||
Write-Host "`nNOTE: Some attributes not available in this environment" -ForegroundColor Yellow
|
|
||||||
Write-Host "The user was created successfully without these attributes" -ForegroundColor Green
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Write-Host "Error accessing source user: $_" -ForegroundColor Red
|
Write-Host "Error accessing source user: $_" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Write-Host "`nScript completed. Press Enter to continue..." -ForegroundColor Gray
|
||||||
|
$null = Read-Host
|
||||||
}
|
}
|
||||||
|
|
||||||
function CopyExistingUser {
|
# Main execution
|
||||||
param (
|
|
||||||
[string]$Domain
|
|
||||||
)
|
|
||||||
|
|
||||||
$sourceUsername = Read-Host "Enter username of the user you want to copy"
|
|
||||||
|
|
||||||
try {
|
|
||||||
$sourceUser = Get-ADUser -Identity $sourceUsername -Properties * -ErrorAction Stop
|
|
||||||
|
|
||||||
Write-Host "`nCopying settings from: $($sourceUser.Name)" -ForegroundColor Cyan
|
|
||||||
Write-Host "Current OU: $($sourceUser.DistinguishedName)`n" -ForegroundColor Cyan
|
|
||||||
|
|
||||||
# Get the parent OU from the source user's DN
|
|
||||||
$sourceOU = $sourceUser.DistinguishedName -replace '^CN=[^,]+,',''
|
|
||||||
Write-Host "Source user's OU: $sourceOU" -ForegroundColor Cyan
|
|
||||||
|
|
||||||
$firstName = Read-Host "Enter new user's first name [$($sourceUser.GivenName)]"
|
|
||||||
if ([string]::IsNullOrWhiteSpace($firstName)) { $firstName = $sourceUser.GivenName }
|
|
||||||
|
|
||||||
$lastName = Read-Host "Enter new user's last name [$($sourceUser.Surname)]"
|
|
||||||
if ([string]::IsNullOrWhiteSpace($lastName)) { $lastName = $sourceUser.Surname }
|
|
||||||
|
|
||||||
$username = Read-Host "Enter new username (leave blank to auto-generate)"
|
|
||||||
|
|
||||||
if ([string]::IsNullOrWhiteSpace($username)) {
|
|
||||||
$username = ($firstName.Substring(0,1) + $lastName).ToLower()
|
|
||||||
Write-Host "Auto-generated username: $username" -ForegroundColor Yellow
|
|
||||||
}
|
|
||||||
|
|
||||||
$displayName = "$firstName $lastName"
|
|
||||||
|
|
||||||
# Offer choice to use source OU or specify new one
|
|
||||||
$ouChoice = Read-Host "Use same OU as source user? [$sourceOU] (Y/N)"
|
|
||||||
if ($ouChoice -eq 'Y' -or $ouChoice -eq 'y') {
|
|
||||||
$ou = $sourceOU
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$ou = Read-Host "Enter new OU distinguished name (e.g., OU=Users,DC=domain,DC=com)"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Validate OU exists
|
|
||||||
try {
|
|
||||||
$null = Get-ADObject -Identity $ou -ErrorAction Stop
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host "Invalid OU specified: $ou" -ForegroundColor Red
|
|
||||||
Write-Host "Defaulting to source user's OU: $sourceOU" -ForegroundColor Yellow
|
|
||||||
$ou = $sourceOU
|
|
||||||
}
|
|
||||||
|
|
||||||
$password = Get-ValidPassword
|
|
||||||
|
|
||||||
try {
|
|
||||||
# Build fresh email attributes for new user
|
|
||||||
$emailAddress = "$username@$Domain"
|
|
||||||
$proxyAddresses = "SMTP:$emailAddress" # Only the new primary address
|
|
||||||
|
|
||||||
Write-Host "`nSetting email attributes:" -ForegroundColor Cyan
|
|
||||||
Write-Host "EmailAddress: $emailAddress"
|
|
||||||
Write-Host "proxyAddresses: $proxyAddresses`n"
|
|
||||||
|
|
||||||
# Base parameters that will always work
|
|
||||||
$newUserParams = @{
|
|
||||||
GivenName = $firstName
|
|
||||||
Surname = $lastName
|
|
||||||
Name = $displayName
|
|
||||||
DisplayName = $displayName
|
|
||||||
SamAccountName = $username
|
|
||||||
UserPrincipalName = $emailAddress
|
|
||||||
AccountPassword = $password
|
|
||||||
Enabled = $true
|
|
||||||
ChangePasswordAtLogon = $true
|
|
||||||
Path = $ou
|
|
||||||
# Copy these organizational attributes
|
|
||||||
Company = $sourceUser.Company
|
|
||||||
Department = $sourceUser.Department
|
|
||||||
Title = $sourceUser.Title
|
|
||||||
Office = $sourceUser.Office
|
|
||||||
# Set email address
|
|
||||||
EmailAddress = $emailAddress
|
|
||||||
ErrorAction = 'Stop'
|
|
||||||
}
|
|
||||||
|
|
||||||
# Try to add mailNickname if available (with error handling)
|
|
||||||
try {
|
|
||||||
$newUserParams['mailNickname'] = $username
|
|
||||||
Write-Host "Attempting to set mailNickname: $username" -ForegroundColor Cyan
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host "Warning: Could not set mailNickname attribute" -ForegroundColor Yellow
|
|
||||||
Write-Host "This attribute may not exist in your test environment" -ForegroundColor Yellow
|
|
||||||
Write-Host "User will be created without mailNickname (can be added later)" -ForegroundColor Yellow
|
|
||||||
}
|
|
||||||
|
|
||||||
# Try to add proxyAddresses if available (with error handling)
|
|
||||||
try {
|
|
||||||
$newUserParams['proxyAddresses'] = $proxyAddresses
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host "Warning: Could not set proxyAddresses attribute" -ForegroundColor Yellow
|
|
||||||
Write-Host "This attribute may not exist in your test environment" -ForegroundColor Yellow
|
|
||||||
}
|
|
||||||
|
|
||||||
# Copy address fields only if they exist on source
|
|
||||||
if ($sourceUser.StreetAddress) { $newUserParams['StreetAddress'] = $sourceUser.StreetAddress }
|
|
||||||
if ($sourceUser.City) { $newUserParams['City'] = $sourceUser.City }
|
|
||||||
if ($sourceUser.State) { $newUserParams['State'] = $sourceUser.State }
|
|
||||||
if ($sourceUser.PostalCode) { $newUserParams['PostalCode'] = $sourceUser.PostalCode }
|
|
||||||
if ($sourceUser.Country) { $newUserParams['Country'] = $sourceUser.Country }
|
|
||||||
if ($sourceUser.OfficePhone) { $newUserParams['OfficePhone'] = $sourceUser.OfficePhone }
|
|
||||||
|
|
||||||
# Create the user with whatever attributes we can set
|
|
||||||
New-ADUser @newUserParams
|
|
||||||
Write-Host "User $username created successfully in $ou!" -ForegroundColor Green
|
|
||||||
|
|
||||||
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR(
|
|
||||||
[Runtime.InteropServices.Marshal]::SecureStringToBSTR($password))
|
|
||||||
|
|
||||||
# Copy group memberships (excluding Domain Users)
|
|
||||||
$copyGroups = Read-Host "Would you like to copy group memberships? (Y/N)"
|
|
||||||
if ($copyGroups -eq 'Y' -or $copyGroups -eq 'y') {
|
|
||||||
$groups = Get-ADPrincipalGroupMembership -Identity $sourceUsername |
|
|
||||||
Where-Object { $_.Name -ne "Domain Users" }
|
|
||||||
|
|
||||||
if ($groups) {
|
|
||||||
foreach ($group in $groups) {
|
|
||||||
try {
|
|
||||||
Add-ADGroupMember -Identity $group -Members $username -ErrorAction Stop
|
|
||||||
Write-Host "Added to $($group.Name) successfully." -ForegroundColor Green
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host "Error adding to group $($group.Name) : $_" -ForegroundColor Red
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-Host "No additional groups to copy." -ForegroundColor Yellow
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host "Error creating user: $($_.Exception.Message)" -ForegroundColor Red
|
|
||||||
|
|
||||||
if ($_.Exception.Message -like "*parent is not on the list of possible superiors*") {
|
|
||||||
Write-Host "`nTROUBLESHOOTING TIPS:" -ForegroundColor Yellow
|
|
||||||
Write-Host "1. You don't have permission to create users in: $ou" -ForegroundColor Yellow
|
|
||||||
Write-Host "2. Try creating in the default Users container instead" -ForegroundColor Yellow
|
|
||||||
Write-Host "3. Run PowerShell as Domain Administrator" -ForegroundColor Yellow
|
|
||||||
}
|
|
||||||
elseif ($_.Exception.Message -like "*mailNickname*") {
|
|
||||||
Write-Host "`nNOTE: mailNickname attribute not available in this environment" -ForegroundColor Yellow
|
|
||||||
Write-Host "The user was created successfully without this attribute" -ForegroundColor Green
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host "Error accessing source user: $_" -ForegroundColor Red
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Main script execution
|
|
||||||
do {
|
do {
|
||||||
Show-Menu
|
Show-Menu
|
||||||
$selection = Read-Host "Please make a selection"
|
$selection = Read-Host "Please make a selection"
|
||||||
@ -524,18 +444,16 @@ do {
|
|||||||
'1' {
|
'1' {
|
||||||
$domain = Get-DomainSelection
|
$domain = Get-DomainSelection
|
||||||
CreateNewUser -Domain $domain
|
CreateNewUser -Domain $domain
|
||||||
pause
|
|
||||||
}
|
}
|
||||||
'2' {
|
'2' {
|
||||||
$domain = Get-DomainSelection
|
$domain = Get-DomainSelection
|
||||||
CopyExistingUser -Domain $domain
|
CopyExistingUser -Domain $domain
|
||||||
pause
|
|
||||||
}
|
}
|
||||||
'Q' {
|
'Q' {
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
default {
|
default {
|
||||||
Write-Host "Invalid selection. Please try again." -ForegroundColor Red
|
Write-Host "Invalid selection" -ForegroundColor Red
|
||||||
pause
|
pause
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user