I tasked myself with the mission of using Microsoft's Windows 8 ADK to create a bootable Windows PE 4.0 UFD, and save a sysprepped workstation hard drive image (.wim) to the UFD. The UFD's WinPE boot sequence would have a PE-hooked batch file in which the user presses one button, walks away for 20 - 30 minutes and returns to a new PC which is on the Domain, in the correct OU, and has all its drivers loaded and GPO's applied. The renaming and Domain adding portion of this process involved PowerShell's access to the win32_computersystem rename command and Add-Computer.
On my first attempt, I tried to rename the computer and add it to the domain during one boot. It just didn't work. I had to reopen the pre-sysprep image and change the unattend.xml sysprep file's administrator login count from 1 to 2. So the first boot checks then changes the computers name and places a RunOnce registry entry to kick off the second half of the process. The second boot checks the computers name and if it is changed, grabs the IP address and starts a Add-Computer command associated with the OU of the corresponding IP subnet.
The PowerShell script during the first boot will create the computer name, add a regkey reboot hook, rename the computer, and restart it (it becomes passive during the second boot due to the computer name checks):
$ComputerName = ("Domain" + (gwmi win32_systemenclosure).SMBIOSAssetTag)
#A hook into the post-sysprep start script so it can be reran on next boot:
if ((gwmi win32_computersystem).name -ne $ComputerName){reg.exe add HKLM\Software\Microsoft\Windows\CurrentVersion\Runonce /v Restart /t REG_SZ /d "c:\scripts\start.bat" /f}
#Renaming the computer and restarting:
if ((gwmi win32_computersystem).name -ne $ComputerName){(gwmi win32_computersystem).rename($ComputerName);restart-computer}
#The second boot PowerShell script encrypts a domain user/pass,
#determines the PC's IP subnet, then executes Add-Computer and
#places the PC in the correct OU. Upon restart, kicks off GPUpdate at first Domain login.
#determines the PC's IP subnet, then executes Add-Computer and
#places the PC in the correct OU. Upon restart, kicks off GPUpdate at first Domain login.
#Saving the alternate Active Directory credentials:
$Username = "domain\delegateuser"
$Password = convertto-securestring "secret" -asplaintext -force
$Cred = new-object system.management.automation.pscredential($Username,$Password)
#Use ADSI to search for the computer object on the domain.
#If one is found, add-computer with no OU is used. If not then the script
#finds the IP subnet and assigns the computers object to the appropriate OU
$searcher = [adsisearcher][adsi]""
$searcher.filter ="(cn=$ComputerName)"
$searchparm = $searcher.FindOne()
if (!($searchparm)){
#Checking the computer name then finding its IP subnet:
$ComputerName = ("Domain" + (gwmi win32_systemenclosure).SMBIOSAssetTag)
if ((gwmi win32_computersystem).name -ne $ComputerName){write "something went wrong with renaming the computer"|out-gr
idview;cmd /c pause}
idview;cmd /c pause}
$IP = [system.net.dns]::GetHostAddresses($env:computername)|?{$_.IPAddresstostring -like '192.168.*'}
#We've captured IP addresses to two octets and now find the
#Active Directory Site via the third IP octet and perform the
#add-computer command combined with the saved AD credentials and correct OU location:
#Active Directory Site via the third IP octet and perform the
#add-computer command combined with the saved AD credentials and correct OU location:
if ($ip -like '192.168.0.*'){add-computer -domain MyDomain -Credential $cred -OUPath "OU=HQ,OU=WORKSTATIONS,DC=MyDomain,DC=COM"}
if ($ip -like '192.168.1.*'){add-computer -domain MyDomain -Credential $cred -OUPath "OU=Site1,OU=WORKSTATIONS,DC=MyDomain,DC=COM"}
if ($ip -like '192.168.2.*'){add-computer -domain MyDomain -Credential $cred -OUPath "OU=Site2,OU=WORKSTATIONS,DC=MyDomain,DC=COM"}
#closing the if statement concerning finding a computer object or not.
#The Else adds the computer to the domain and reattaching it to it's existing
#computer object
#Update 2/21/14
#I found it more efficient to take away the else statement and instead just create a catch-all: add-computer -domain MyDomain -Credential $cred
#Another problem was re-imaging existing domain computers. AD would try
#creating another GUID and cause GPO and other problems.
#To fix this, I added:
start-process powershell.exe -credential $cred -argumentlist 'if (!(test-computersecurechannel)){test-computersecurechannel -repair}
#so if the computer is in the domain but not in one of the above mentioned subnets, it'll still be added to the domain.
}else{add-computer -domain MyDomain -Credential $cred}
#The Else adds the computer to the domain and reattaching it to it's existing
#computer object
#Update 2/21/14
#I found it more efficient to take away the else statement and instead just create a catch-all: add-computer -domain MyDomain -Credential $cred
#Another problem was re-imaging existing domain computers. AD would try
#creating another GUID and cause GPO and other problems.
#To fix this, I added:
start-process powershell.exe -credential $cred -argumentlist 'if (!(test-computersecurechannel)){test-computersecurechannel -repair}
}else{add-computer -domain MyDomain -Credential $cred}
#The computer is now a member of the Domain. Next add a
#Registry RunOnce key entry so the next boot will start a
#forced application of GPUpdate relevant to it's OU:
#Registry RunOnce key entry so the next boot will start a
#forced application of GPUpdate relevant to it's OU:
reg.exe add HKLM\Software\Microsoft\Windows\CurrentVersion\Runonce /v GPUpdate /t REG_SZ /d "gpupdate /force" /f
Lastly, delete the scripts with passwords in them and restart the computer so it can change its network affiliation from WORKGROUP to the new Domain assignment:
reg.exe add HKLM\Software\Microsoft\Windows\CurrentVersion\Runonce /v DelPS1 /t REG_SZ /d "del c:\scripts*.ps1 /q" /f
restart-computer
This process works and has a positive side-effect: It stops the computer from joining the domain if the Computer Object already exists (which stops any sort of SID problems or unintended OU movements).
It's been suggested by a fellow Redditor that I should create a switch instead of the If statements breaking down the IP subnets. I'll update this post after I've tested that portion. Let me know if you have any questions, comments, or suggestions.