[powershell] Rename computer and join to domain in one step with PowerShell

Goal: On a computer running Windows Server 2008 R2, use PowerShell 2.0 to:

  1. Rename the computer
  2. Join the computer to a domain

Condition: Steps 1 and 2 must be performed together, i.e., without a computer restart between them

Functions I'm Using

These are the PowerShell functions I've created for each step.

Rename Computer

According to my Internet research, PowerShell 2.0 at one point before release had a built-in cmdlet called Rename-Computer, but it was removed for reasons unknown in CTP 3. My version uses WMI.

function Rename-Computer
{
    param ( [Parameter(Mandatory=$true)][string]$name )

    process
    {
        try
        {
            $computer = Get-WmiObject -Class Win32_ComputerSystem
            $result = $computer.Rename($name)

            switch($result.ReturnValue)
            {       
                0 { Write-Host "Success" }
                5 
                {
                    Write-Error "You need administrative rights to execute this cmdlet" 
                    exit
                }
                default 
                {
                    Write-Host "Error - return value of " $result.ReturnValue
                    exit
                }
            }
        }
        catch
        {
            Write-Host "Exception occurred in Rename-Computer " $Error
        }
    }
}

Join Computer to Domain

As you can see, this function is really just a wrapper for the built-in cmdlet Add-Computer that gathers the domain name and creates some credentials to use.

function Join-ComputerToDomain
{
    param ( [Parameter(Mandatory=$true)][string]$domain )

    process
    {
        try
        {
            $_domainCredential = $Host.UI.PromptForCredential("Enter domain credentials", "Enter domain credentials to be used when joining computer to the domain", "", "NetBiosUserName")
            Add-Computer -DomainName $_domain -cred $_domainCredential
        }
        catch
        {
            Write-Error "Exception occurred in Join-ComputerToDomain " $Error
        }
    }
}

Steps I've Tried

Attempt 1

  1. Call Rename-Computer
  2. Call Join-ComputerToDomain
  3. Restart

Result: Output from Rename-Computer indicates that name was changed, but after restart, name did not change, but computer was joined to domain

Attempt 2

  1. Call Join-ComputerToDomain
  2. Call Rename-Computer
  3. Restart

Result: Return value from Rename-Computer is 1326 (Logon failure: unknown user name or bad password). I assume this is because domain credentials are required for the rename once it's joined to the domain. I attempted to use credentials with the Get-WmiObject call in Rename-Computer, but it threw an error about not being able to use different credentials on the local system.

Attempt 3

  1. Call Rename-Computer
  2. Restart
  3. Call Join-ComputerToDomain
  4. Restart

Result: Everything works as expected, but extra restart required. Works but I want to eliminate the restart at step 2.

This question is related to powershell powershell-2.0

The answer is


This solution is working:

  • Enter the computer in the Active Directory domain with authentication (no Restart)
  • Rename the computer with authentication (no Restart)
  • after, Restart

In code:

# get the credential 
$cred = get-credential

# enter the computer in the right place
Add-Computer -DomainName EPFL -Credential $cred -OUPath "...,DC=epfl,DC=ch"

# rename the computer with credential (because we are in the domain)
$Computer = Get-WmiObject Win32_ComputerSystem
$r = $Computer.Rename("NewComputerName", $cred.GetNetworkCredential().Password, $cred.Username)

I have a tested code to join domain and rename the computer to the servicetag.

code:

$servicetag = Get-WmiObject win32_bios | Select-Object -ExpandProperty SerialNumber
Add-Computer -Credential DOMAIN\USER -DomainName DOMAIN -NewName $servicetag

DOMAIN\USER = edit to a user on the domain that can join computers to the domain. Example:

mydomain\admin

DOMAIN = edit to the domain that you want to join. Example:

mydomain.local

Also add local account + rename computer at prompt + join to domain at promt

#Set A local admin account
$computername = $env:computername   # place computername here for remote access
$username = 'localadmin'
$password = 'P@ssw0rd1'
$desc = 'Local admin account'
$computer = [ADSI]"WinNT://$computername,computer"
$user = $computer.Create("user", $username)
$user.SetPassword($password)
$user.Setinfo()
$user.description = $desc
$user.setinfo()
$user.UserFlags = 65536
$user.SetInfo()
$group = [ADSI]("WinNT://$computername/administrators,group")
$group.add("WinNT://$username,user")

# Set computer name 
$computerName = Get-WmiObject Win32_ComputerSystem 
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null 
$name = [Microsoft.VisualBasic.Interaction]::InputBox("Enter Desired Computer Name ")
$computername.rename("$name")

#Now Join to Domain
Add-Computer -DomainName [domainname] -Credential [user\domain]  -Verbose
Restart-Computer

As nobody answer, I try something :

I think I understand why Attent one does not work. It's because joining a computer to a domain is somehow also renaming the computer (the domain name part, enter in the name of the machine).

So do you try to do it in full WMI way, you've got a method in Win32_ComputerSystem class called JoinDomainOrWorkgroup. Doing it on the same level perhaps gives you more chance to make it work.


Rename-Computer was removed from CTP3 because there are a lot of things done when renaming a computer and MS either didn't want to recreate that process or couldn't include all of the necessary bits. I think Jefferey Snover said to just use netdom.exe instead, as that is the best practice for renaming a computer on the command-line. Not the answer you were looking for, but should point you in the right direction


There are actually several reasons that you have to reboot after renaming a computer, or when joining a domain (which is basically the same operation with validation by AD). One being that on NT based computers (I believe this started with Windows 2000), the Application and Network services read the computer name when they are started. Which is the only time they read the computer name, so if you were to rename the computer without a restart, the network and application services would not respond to the new computer name. This particularly becomes important when you are first renaming the computer, and then trying to join a domain, as the kerberos handshake can not be completed without the network stack responding to the correct computer name.

Another reason is that several registry keys make use of the computer name, and those keys cannot be changed while they are loaded into memory (this is incidentally also why some programs require a reboot to complete installation or uninstallation).

You could use the RunOnce registry key (msdn.microsoft.com/en-us/library/aa376977%28v=vs.85%29.aspx) to run your domain join script automatically upon reboot, but you're still going to have to reboot for both operations.

If you really wanted to get tricky, you could add some code to your rename script that would set the RunOnce registry key to launch the domain join script upon reboot. Be aware though if you are going to do this, that the script that will be writing to the HKLM hive must be run as an administrator (especially important if you have UAC turned on).

If you want to do that, you'd use something like this at the end of your Rename-Computer function:

Set-Location -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce'
Set-ItemProperty -Path . -Name joinDomain -Value "C:\scripts\joinDomain.ps1"
Restart-Computer

This will create a subkey in the RunOnce registry key (assuming you are running Vista/7/2008) named "joinDomain" with the value of "C:\scripts\joinDomain.ps1"

If that doesn't work for you, try changing the second line to this:

Set-ItemProperty -Path . -Name joinDomain -Value 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe "C:\scripts\joinDomain.ps1"'

Let me know if you have troubles.


If you create the machine account on the DC first, then you can change the name and join the domain in one reboot.


This will prompt for computer name and join to domain then restart.

$computerName = Get-WmiObject Win32_ComputerSystem 
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null 
$name = [Microsoft.VisualBasic.Interaction]::InputBox("Enter Desired Computer Name ")
$computername.rename("$name")
Add-Computer -DomainName [domainname] -Credential [user\domain]  -Verbose
Restart-Computer

I would like to offer the following that worked in an automated capacity for me. It shows the sequence of steps and the relationship between setting the name first, then joining the domain. I use this in a script as an orchestration point for Win2008r2 and win2012r2 via Scalr CMP for EC2 and Openstack cloud instances.

$userid="$DOMAIN\$USERNAME"
$secure_string_pwd = convertto-securestring "SECRET_PASSWORD" -asplaintext -force
$creds = New-Object System.Management.Automation.PSCredential $userid,$secure_string_pwd

Rename-Computer "newhostname" -DomainCredential $creds -Force
WARNING: The changes will take effect after you restart the computer OLDHOSTNAME.

Add-Computer -NewName "newhostname" -DomainName $DOMAIN -Credential $creds \
-OUPath "OU=MYORG,OU=MYSUBORG,DC=THEDOMAIN,DC=Net" -Force
WARNING: The changes will take effect after you restart the computer OLDHOSTNAME.

Restart-Computer

One caveat is to be careful with the credentials, pull them from a key store rather than hard-coded as illustrated here ... but that's a different topic.

Thanks, everyone, for your answers.


In one-step w/admin credentials:

Add-Computer -DomainName xxxx -ComputerName xxxx -NewName xxxx -Credential Domain\Admin -Restart

-DomainName = Your domain name (e.g. corp.local)

-ComputerName = Name of your local computer (e.g. The computer you are on. Use "Hostname" in PS to find out name).

-NewName = What you want to rename the computer (e.g. CORP-ANNE-TX)

-Credentials = Your admin credentials that give you authorization to perform this action (e.g. Domain\Admin = example Corp\JSmith. A dialog box will appear to put in your password)

In two-steps:

Step 1

Rename-Computer -NewName xxxx -Restart

Here you do not have to put -ComputerName as it assumes you are at the local computer. If doing this remotely; different story.

Step 2

Add-Computer -DomainName xxxx -Credential xxxx\xxxxx -Restart

xxxx\xxxx = Your domain and admin username (e.g. Corp\Jsmith)


Here is another way to do with "Computer Name/Domain Change" Windows of System Properties.

In other words, bring up System Properties| Computer Name Tab then click Change using powershell. It is different approach, it is useful in my situation and it could be helpful for someone else.

add-type -AssemblyName microsoft.VisualBasic add-type -AssemblyName System.Windows.Forms

SystemPropertiesComputerName start-sleep –Seconds 1

[Microsoft.VisualBasic.Interaction]::AppActivate(“System Properties”)

[System.Windows.Forms.SendKeys]::SendWait(“{TAB}”) start-sleep –Seconds 1

[System.Windows.Forms.SendKeys]::SendWait(“{ENTER}”)


the Options JoinWithNewName in Add-Computer can do this work .

-- JoinWithNewName: Renames the computer name in the new domain to the name specified by the NewName parameter. When you use the NewName parameter, this option is set automatically. This option is designed to be used with the Rename-Computer cmdlet. If you use the Rename-Computer cmdlet to rename the computer, but do not restart the computer to make the change effective, you can use this parameter to join the computer to a domain with its new name.

$oldName = Read-Host -Prompt "Enter Original Computer Name"
$newName = Read-Host -Prompt "Enter New Computer Name"
$domain = Read-Host -Prompt "Enter Domain Name to be added"
$user = Read-Host -Prompt "Enter Domain user name"
$password = Read-Host -Prompt "Enter password for $user" -AsSecureString 
$username = "$domain\$user" 
$credential = New-Object System.Management.Automation.PSCredential($username,$password) 
Rename-Computer -NewName $newName -LocalCredential admin -Force
Write-Host "Please waiting for a moment to change Domain and then restart" -ForegroundColor Red
Add-Computer -ComputerName $oldName -DomainName $domain -Options JoinWithNewName -Credential $credential -Restart

$domain = "domain.local"
$password = "Passw@rd" | ConvertTo-SecureString -asPlainText -Force
$username = "$domain\Administrator"
$hostname=hostname
$credential = New-Object System.Management.Automation.PSCredential($username,$password)
Add-Computer -DomainName $domain -ComputerName $hostname -NewName alrootca -Credential $credential -Restart

Works for me ^^


I had a slightly augmented issue. I needed to rename a machine and then RE-JOIN a domain it was already a member of and could not find where to do that but its seems very close to what is here. The individual solutions above don't do it but with some togetherness... If you try to rename, you get denied. If you rename and then rejoin, you get an account already exists error. You need to bail from the domain by joining a workgroup and then you can run the rename and join in one command.

$Chops = Get-Credential 
# Or bring in a stored credential
$NewComputerName = "WhoImGonnaBe" 
# or value from CSV
$MyDomainName = "MyDomain"
Add-Computer -WorkgroupName NotADomain -force -DomainCredential $Chops
Add-Computer -DomainName $MyDomainName -Computername $ENV:Computername -NewName $NewComputerName -DomainCredential $Chops -Force -Restart
#  If running locally you really only need the -NewName and can omit the -Computername

I was able to accomplish both tasks with one reboot using the following method and it worked with the following JoinDomainOrWorkGroup flags. This was a new build and using Windows 2008 R2 Enterprise. I verified that it does create the computer account as well in AD with the new name.

1 (0x1) Default. Joins a computer to a domain. If this value is not specified, the join is a computer to a workgroup

32 (0x20) Allows a join to a new domain, even if the computer is already joined to a domain

$comp=gwmi win32_computersystem
$cred=get-credential
$newname="*newcomputername*"
$domain="*domainname*"
$OU="OU=Servers, DC=domain, DC=Domain, DC=com"
$comp.JoinDomainOrWorkGroup($domain ,($cred.getnetworkcredential()).password, $cred.username, $OU, 33)
$comp.rename($newname,$cred.getnetworkcredential()).password,$cred.username)

I was looking for the same thing today and finally got a way to do it. I was hinted that it was possible due to the use of sconfig, which ask you if you want to change the computer name after joining it to a domain. Here is my raw code line. It might be enhanced but to tired to think about it for now.

$strCompName = Read-host 'Name '
$strAdmin = read-host "Authorized user for this operation "
$strDomain = read-host "Name of the domain to be joined "
add-computer -DomainName $strDomain -Credential $strAdmin
Rename-computer -newname $strCompName -DomainCredential $strAdmin