Join A Computer to Domain and Place in Correct OU Based on AD Site Membership

Multi tool use
Join A Computer to Domain and Place in Correct OU Based on AD Site Membership
How can I create a PowerShell script capable of doing the task above?
I have come up with a collection of codes that eventually made up a PowerShell script that made use of the Add-Computer
comdlet to rename a computer, join it to the domain, move it to an OU based on the input provided by the one running the script, and restart the machine. I was previously given the information that AD cannot be queried (e.g. to get AD site information) from a workgroup computer, but articles on authenticated LDAP queries from unjoined computers abound on the Internet, so it means I just need the right set of codes.
Add-Computer
The logic of the script should be simple enough. At run-time, the script does the following...
SO far, here's the code that I have:
# CMD.exe /c powershell -executionpolicy bypass C:scriptLocationthisScript.ps1
# ==============================================================================
# Function RESTART Y-N
Function RestartYN {
$Restart=''
WHILE ($Restart -notin 'y', 'n') {
Write-Host "Please make sure to save your work if you wish to restart the computer now. " -foregroundcolor magenta -backgroundcolor white
Write-Host
Write-Host " Restart this computer now? (Y/N)? " -foregroundcolor black -backgroundcolor yellow
Write-Host " [ Y = NOW | N = LATER ] " -foregroundcolor black -backgroundcolor yellow -nonewline
$Restart = Read-Host
Write-Host
}
IF ($Restart -eq 'y') {
Write-Host
Write-Host "You have answered 'Yes'. Pressing any key will restart this computer... " -foregroundcolor yellow -backgroundcolor darkgreen
Write-Host
[void][System.Console]::ReadKey($true)
Write-Host "The computer is now RESTARTING..." -foregroundcolor magenta
Restart-Computer -force
}
ELSEIF ($Restart -eq 'n') {
Write-Host
Write-Host "You have answered 'No'. Changes will take effect when computer is restarted." -foregroundcolor yellow -backgroundcolor darkred
Write-Host
Write-Host "Ending this script... This session will end as soon as you press any key... " #-nonewline
Write-Host " " -nonewline
[void][System.Console]::ReadKey($true)
Write-Host
EXIT
}
}
# ==============================================================================
# Function Get credentials first
Function Get-CredsFIrst {
$Creds = Get-Credential -Message "Enter the domain account to use in executing this operation (eg. TESTDOMAINUserName):" -EA SilentlyContinue -WarningAction SilentlyContinue -ev getCredEV
$username = $creds.username
$password = $creds.GetNetworkCredential().password
# Get current domain using logged-on user's credentials
$CurrentDomain = "LDAP://" + ([ADSI]"").distinguishedName
$domain = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain,$UserName,$Password)
if ($creds -eq $null)
{
Write-Host
write-host "Credentials are empty. Please enter your credentials and make sure they are not empty." -foregroundcolor red -backgroundcolor white
Write-Host
Get-CredsFIrst
}
else
{
Write-Host
ExecJoin
}
}
# ==============================================================================
# Function: Execute Join: FINAL COMMAND if all else works: Join the computer to the domain, rename it, and restart it.
FUNCTION ExecJoin {
Write-Host " ~~~~~~ Attempting to perform requested operation. Please wait... ~~~~~~ " -foregroundcolor magenta -backgroundcolor white
$LocDN = "OU=$OU2,OU=OFFICES,DC=testdom,dc=net"
$Result=Add-Computer -DomainName testdom.net -OUPath $LocDN -Credential $Creds -NewName $WS_NewName -passthru -Errorvariable ACError -EA SilentlyContinue -WarningAction SilentlyContinue
Write-Host
IF ($Result.hasSucceeded)
{ Write-Host " ======== This computer has been successfully joined to TESTDOMAIN. ========= " -ForeGroundColor white -backgroundcolor darkgreen
Write-Host
Write-Host "----------------------------------------------------------------------------" -foreground green
Write-Host " CHANGES Successfully Made to this Computer" -foreground green
Write-Host " Please note that the following changes were " -nonewline
Write-Host "successfully" -foregroundcolor white -backgroundcolor darkgreen -nonewline
Write-Host " made "
Write-Host " to this computer as a result of this operation:"
Write-Host
Write-Host
Write-Host " * Computer's NEW NAME : " -nonewline
Write-Host $WS_NewName -foregroundcolor green
Write-Host
Write-Host " * Joined DOMAIN : " -nonewline
Write-Host "TESTDOMAIN" -foregroundcolor green
Write-Host
Write-Host " * OU (TWO-LETTER Code) : " -nonewline
Write-Host $OU2 -foregroundcolor green
Write-Host " "
Write-Host " * Location Name : " -nonewline
Write-Host $OUlong -foregroundcolor green
Write-Host " "
Write-Host
Write-Host " This computer has to be restarted for the changes to take effect. " -ForegroundColor black -backgroundcolor darkYellow
Write-Host
RestartYN
}
ELSE # ($Result.hasNotSucceeded)
{ Write-Host " ==== Error performing the operation. See resulting message below. ===== " -foregroundcolor white -backgroundcolor red
Write-Host
Write-Host $ACError[0].Exception.Message -ForegroundColor yellow # -backgroundcolor yellow
Write-Host
Write-Host "============================================================================" -foregroundcolor red
Write-Host
Write-Host
Write-Host " To resolve errors, please make sure the following prerequisite conditions are met:"
Write-Host
Write-Host " (1) Verify that this computer has not already been joined to TESTDOMAIN." -foregroundcolor yellow
Write-Host " Also make sure that this computer has no pending reboot requirement." -foregroundcolor yellow
Write-Host " (2) Verify PROPER DNS SERVER IP ADDRESS values in network adapter settings." -foregroundcolor yellow
Write-Host " A good indication is if you can SUCCESSFULLY PING the domain testdom.net." -foregroundcolor yellow
Write-Host " (3) Verify that you are using VALID CREDENTIALS and that the account has" -foregroundcolor yellow
Write-Host " the REQUIRED PERMISSIONS to join this computer to the domain." -foregroundcolor yellow
Write-Host " (4) Verify that the NEW COMPUTER NAME is VALID and AVAILABLE for use."-foregroundcolor yellow
Write-Host
Write-Host " If you would need assistance resolving the errors, please contact support." -foregroundcolor darkyellow
Write-Host
Write-Host " If you would like to retry this task without exiting, you may do so. " -foregroundcolor cyan -backgroundcolor darkgray
Write-Host
Pause
RETRY
}
}
# ==============================================================================
# Funtion: Retry if JOIN fails for whatever reason
Function Retry {
$Retry = ''
WHILE ($Retry -notin 'y', 'n') {
Write-Host " Would you like to RETRY this JOIN operation? (Y/N)" -foregroundcolor yellow
Write-Host " [Ctrl+C terminates script] " -foregroundcolor darkgray -nonewline
Write-Host
Write-Host ' [ Y - Retry | N - End ] ' -foreground yellow -nonewline
$Retry = Read-Host
Write-Host }
IF ($Retry -eq 'y') {
Write-Host
Write-Host "You have answered 'Yes'. You will need to define your parameters again. " -foregroundcolor darkgreen -backgroundcolor white
Write-Host
Pause
$WS_NewName = $null
$OU2 = $null
$OUlong = $null
clear-host
Define-Parameters
} ELSEIF ($Retry -eq 'n') {
Write-Host
Write-Host "You have answered 'No'. If you must retry, Please run this script again. " -foregroundcolor yellow -backgroundcolor darkgray
Write-Host
Write-Host "Ending this script... This session will end as soon as you press any key... " #-nonewline
Write-Host " " -nonewline
[void][System.Console]::ReadKey($true)
Write-Host
EXIT
}
}
# ==============================================================================
# Function: Y/N
FUNCTION YesOrNo {
$Answer = ''
WHILE ($Answer -notin 'y', 'n') {
Write-Host "If the parameters above are correct, you may proceed."
Write-Host "Otherwise, you can enter them again."
Write-Host
Write-Host "[Ctrl+C terminates script] " -foregroundcolor darkgray # -nonewline
Write-Host 'All correct and ready to proceed? [Y/N] ' -foreground yellow -nonewline
$Answer = Read-Host
Write-Host }
IF ($Answer -eq 'y') {
Write-Host
Write-Host "You have answered 'Yes'. You will now be asked for your user credentials. " -foregroundcolor darkgreen -backgroundcolor white
Write-Host
Pause
# Write-Host
Write-Host
Write-Host "Please enter your credentials for this operation and wait for the results. " -foregroundcolor magenta -backgroundcolor white
# Write-Host
Get-CredsFIrst
} ELSEIF ($Answer -eq 'n') {
Write-Host
Write-Host "You have answered 'No'. You will need to define your parameters again. " -foregroundcolor yellow -backgroundcolor darkgray
Write-Host
$WS_NewName = $null
$OU2 = $null
$OUlong = $null
Pause
Clear-Host
Define-Parameters
}
}
# ==============================================================================
# Function: Summary and confirmation screen for defined parameters.
FUNCTION Confirm-Parameters {
Write-Host "----------------------------------------------------------------------------" -foreground yellow
Write-Host " CONFIRM Your Parameters" -foreground yellow
Write-Host " Please confirm that you are joining this computer to " -nonewline
Write-Host "TESTDOMAIN" -foregroundcolor darkblue -backgroundcolor gray -nonewline
Write-Host " with" # -foreground yellow
Write-Host " the following parameters:" # -foreground yellow
Write-Host
Write-Host " * Computer's NEW NAME : " -nonewline
Write-Host $WS_NewName -foregroundcolor yellow
Write-Host
Write-Host " * TARGET location OU : " -nonewline
Write-Host $OU2 -foregroundcolor yellow
Write-Host " "
Write-Host " * Office location : " -nonewline
Write-Host $OUlong -foregroundcolor yellow
Write-Host " "
YesOrNo
}
# ==============================================================================
# Function: Define the parameters
Function Define-Parameters {
$WS_NewName = $null
$OU2 = $null
$OUlong = $null
Write-Host "----------------------------------------------------------------------------" -foreground cyan
Write-Host " DEFINE Your Parameters" -foreground cyan
Write-Host " Please enter needed values for joining this computer to " -nonewline
Write-Host "TESTDOMAIN" -foregroundcolor darkblue -backgroundcolor gray -nonewline
Write-Host ":"
Write-Host
Set-WSName
}
# Function Set New WS Name
Function Set-WSName {
$WS_NewName = $null
DO {
$WS_NewName = Read-Host -Prompt " * NEW NAME of computer (8-15 chars) "
} UNTIL ($WS_NewName.Length -gt 7 -and $WS_NewName.Length -lt 16) # -and $WS_NewName -notmatch '^d+$' -and $WS_NewName -notmatch 'desktop*' -and $WS_NewName -match '^w[w-]*$')
''
$WS_NewName = $WS_NewName.ToUpper()
IF ($WS_NewName -match '^d+$' -or $WS_NewName -match 'desktop*' -or $WS_NewName -notmatch '^w[w-]*$')
{
Write-Host "Warning: " -foregroundcolor yellow -nonewline
Write-Host "$WS_NewName" -foregroundcolor yellow -backgroundcolor darkgray -nonewline
Write-Host " is NOT valid as a new name." -foregroundcolor yellow
Write-Host
Write-host -foregroundcolor darkyellow "Name can consist of alphanumeric characters (A-Z, a-z, 0-9), but cannot "
Write-host -foregroundcolor darkyellow "consist purely of numeric ones (0-9), should not start with 'DESKTOP' or"
Write-host -foregroundcolor darkyellow "'desktop', and cannot contain spaces or periods (.). Please try again."
Write-Host
Set-WSName
}
Else {
SetOU
}
}
# ==============================================================================
# Function Set OU value
Function SetOU {
$OU2 = $null
$OUlong = $null
Write-Host
DO {
$OU2 = Read-Host -Prompt " * Target OU (TWO-LETTER location code) "
} UNTIL ($OU2 -match '^[a-z]{2}$')
''
$WS_NewName = $WS_NewName.ToUpper()
$OU2=$OU2.ToUpper()
IF ($OU2 -eq 'HQ') {
$OUlong = 'Head Quarters'
} ELSEIF ($OU2 -eq 'NA') {
$OUlong = 'North America'
} ELSEIF ($OU2 -eq 'SA') {
$OUlong = 'South America'
} ELSEIF ($OU2 -eq 'EU') {
$OUlong = 'Europe'
} ELSEIF ($OU2 -eq 'AS') {
$OUlong = 'Asia'
}
ELSE {
Write-Host "Warning: " -foregroundcolor yellow -nonewline
Write-Host "$OU2" -foregroundcolor yellow -backgroundcolor darkgray -nonewline
Write-Host " is NOT yet defined in script as an existing OU in AD." -foregroundcolor yellow
Write-Host
Write-Host "Value entered should be a valid 2-letter code for the office where the" -foregroundcolor darkyellow
Write-Host "computer being joined belongs to. Please make sure you enter a valid " -foregroundcolor darkyellow
Write-Host "OU (or contact support regarding this error." -foregroundcolor darkyellow
SetOU
}
$WS_NewName = $WS_NewName.ToUpper()
$OU2=$OU2.ToUpper()
Confirm-Parameters
}
# ==============================================================================
# Function: PAUSE
FUNCTION Pause ($Message = " Press any key to continue . . . ") {
IF ((Test-Path variable:psISE) -and $psISE) {
$Shell = New-Object -ComObject "WScript.Shell"
$Button = $Shell.Popup("Click OK to continue.", 0, "Script Paused", 0)
}
ELSE {
Write-Host " [Ctrl+C terminates script] " -foregroundcolor darkgray # -nonewline
Write-Host $Message -NoNewline
[void][System.Console]::ReadKey($true)
}
Write-Host
Write-Host
}
# ==============================================================================
# Funtion: RETRY-nwtest if previous nwtest fails for whatever reason
Function RETRY-nwtest {
$nwtestRetry = ''
WHILE ($nwtestRetry -notin 'y', 'n') {
Write-Host
Write-Host "Would you like to RETRY the name resolution check? (Y/N)" -foregroundcolor yellow
Write-Host "[Ctrl+C terminates script] " -foregroundcolor darkgray # -nonewline
Write-Host '[ Y - Retry | N - End ] ' -foreground yellow -nonewline
$nwtestRetry = Read-Host
Write-Host }
IF ($nwtestRetry -eq 'y') {
Write-Host
Write-Host "You have answered 'Yes'. Will now proceed to repeat name resolution check. " -foregroundcolor darkgreen -backgroundcolor white
Write-Host
Pause
$WS_NewName = $null
$OU2 = $null
$OUlong = $null
clear-host
TestNR
} ELSEIF ($nwtestRetry -eq 'n') {
Write-Host
Write-Host "You have answered 'No'. If you must retry, Please run this script again. " -foregroundcolor yellow -backgroundcolor darkgray
Write-Host
Write-Host "Ending this script... This session will end as soon as you press any key... " #-nonewline
Write-Host " " -nonewline
[void][System.Console]::ReadKey($true)
Write-Host
EXIT
}
}
# ==============================================================================
# Function: Test Name Resolution
FUNCTION TestNR {
Write-Host
Write-Host "Testing name resolution for domain name " -foregroundcolor magenta -backgroundcolor white -NoNewline
Write-Host "testdom.net" -foregroundcolor darkgreen -backgroundcolor white -NoNewline
Write-Host ". Please wait for result... " -foregroundcolor magenta -backgroundcolor white # -NoNewline
$testnrtask=Test-Connection -count 3 -ComputerName "testdom.net" -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
Write-Host
IF ($testnrtask.hasSucceeded)
{
Test-Connection -ComputerName "testdom.net" -count 1
Write-Host
Write-Host "This computer successfully resolves the name " -foregroundcolor green -nonewline
Write-Host "testdom.net" -foregroundcolor darkgreen -BackgroundColor white -nonewline
Write-Host ". Proceeding to the next step... " -foregroundcolor green
Write-Host
pause
Clear-Host
Define-Parameters
}
ELSE
{
Test-Connection -count 1 -ComputerName "testdom.net" -ErrorVariable tcerror -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
Write-Host
write-host $tcerror[0].Exception.Message -ForegroundColor Yellow
Write-Host
Write-Host "--------------------------------------------------------------------------- " -foregroundcolor yellow # -backgroundcolor white
Write-Host
Write-Host " Check your network connection status. Verify PROPER DNS SERVER IP ADDRESS" -foregroundcolor darkyellow # -backgroundcolor darkred
Write-Host " value(s) in your network adapter settings. A good indication of this" -foregroundcolor darkyellow # -backgroundcolor darkred
Write-Host " is if you can SUCCESSFULLY RESOLVE and PING the DNS domain name of the" -foregroundcolor darkyellow # -backgroundcolor darkred
Write-Host " Active Directory domain that you are joining (in this case, testdom.net)." -foregroundcolor darkyellow # -backgroundcolor darkred
Write-Host
Write-Host " After making the necessary corrections to your network settings, you may repeat this check. " -foregroundcolor darkcyan -backgroundcolor black
Write-Host
Pause
Write-Host
Write-Host
RETRY-nwtest
}
}
# ==============================================================================
# Function: CheckNW
FUNCTION CheckNW {
$choice = ''
WHILE ($choice -notin 'y', 'n') {
Write-Host "Would you like to check if name resolution is working for the name " -foreground darkyellow -nonewline
Write-Host "testdom.net" -foreground darkblue -backgroundcolor gray -nonewline
Write-Host "? (Y/N)" -foreground darkyellow
Write-Host "[Ctrl+C terminates script] " -foregroundcolor darkgray
Write-Host '[ Y - Check | N - Skip ] ' -nonewline
$choice = Read-Host
Write-Host }
IF ($choice -eq 'y') {
Write-Host
Write-Host "You have answered 'Yes'. Will now proceed with the name resolution check. " -foregroundcolor darkgreen -backgroundcolor white
Write-Host
Pause
Clear-Host
TestNR
} ELSEIF ($choice -eq 'n') {
Write-Host
Write-Host "You have answered 'No'. Will now skip the step to check name resolution. " -foregroundcolor yellow -backgroundcolor darkgray
Write-Host
$WS_NewName = $null
$OU2 = $null
$OUlong = $null
Pause
Clear-Host
Define-Parameters
}
}
# ==============================================================================
# START: Display name and purpose of invoked script
Set-ItemProperty -ea silentlycontinue "HKLM:SOFTWAREMicrosoftPowerShell1ShellIds" -Name "ConsolePrompting" -Value $True
$Path = $MyInvocation.MyCommand.Definition
Clear-Host
Write-Host " "
Write-Host -foreground cyan "Now running [" -nonewline
Write-Host $path -foregroundcolor yellow -nonewline
Write-Host -foreground cyan "]. This will allow you to do the following in a single-step process:"
Write-Host " "
Write-Host "(1)" -foreground gray -nonewline
Write-Host " RENAME " -foreground cyan -nonewline
Write-Host "this computer" -foreground gray
Write-Host "(2)" -foreground gray -nonewline
Write-Host " JOIN " -foreground cyan -nonewline
Write-Host "it to TESTDOMAIN" -foreground gray
Write-Host "(3)" -foreground gray -nonewline
Write-Host " MOVE " -foreground cyan -nonewline
Write-Host "it to target OU" -foreground gray
Write-Host "(4)" -foreground gray -nonewline
Write-Host " REBOOT " -foreground cyan
Write-Host " "
Write-Host " "
Write-Host "PREREQUISITE" -foreground darkmagenta -BackgroundColor gray -nonewline
Write-Host ": Please make sure you are configured with the correct DNS server IP address."
Write-Host " If so, you should be able to at least " -nonewline
Write-Host "PING testdom.net" -foreground darkyellow -nonewline
Write-Host "."
Write-Host " "
CheckNW
EXIT
What I couldn't figure out is the right code that would include the use of an LDAP connection to read AD sites info from CN=Sites,CN=Configuration,DC=Testddom,DC=net
, and code to create the necessary IF
conditions based on the site(s)-to-OU matching to determine the value that should be used for the variable $OUlong
, which should contain the DN
of the OU
where the computer's AD account should be placed (instead of a manual input from the one running the script).
CN=Sites,CN=Configuration,DC=Testddom,DC=net
IF
$OUlong
DN
OU
Thanks, @robdy. I edited my question and added the code.
– Jee
Jul 4 at 11:28
I'm just wondering if it wouldn't be easiest to just perform domain join to some temporary OU and then (e.g. once a day) run script on another server to move the machine to correct OU - to not overcomplicate the things.
– robdy
Jul 4 at 12:38
Thanks. That would really be nice and a lot less complicated, esp. if, to start with, the domain has more than 400 sites that would need to be matched to 150+ second-level child OUs (at least), having as many local IT admins that would be using the script. And best practice would tell us to just pre-create computer accounts in the right OU, which the local IT guys could do, and which would really make life a lot easier for whoever would need to create the script. But bosses have a tendency to go in a different direction :-).
– Jee
Jul 4 at 13:49
Gotcha! I won't be able to help you with troubleshooting but you can start here or here.
– robdy
Jul 4 at 14:32
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Hello @Jee. As already suggested here would be nice if you posted some code you already have and list the issues you have with that so that community can help you. Stack Overflow is not free code writing service so showing your effort will increase chances for getting good answers.
– robdy
Jul 3 at 13:45