Touch-Free PowerShell DCPROMO in Windows Server 2012
DCPROMO Keeping You Up At Night?
Do you schedule DCPROMO activities for the weekend? After hours? Middle of the night? I remember those days. Often it was hard to get in the right frame of mind to think through all of the exact procedural steps during those late night change controls. It was always good to have a thorough implementation plan.
Today’s post will show you how to easily promote and demote a Windows Server 2012 domain controller remotely with a script. You don’t even need to logon to the target server.
PowerShell DCPROMO in Windows Server 2012
In Windows Server 2012 DCPROMO is gone. The replacement is the ADDSDeployment module, and it is packed full of PowerShell goodness. Another key fact is that remoting is enabled by default in Windows Server 2012. See the potential here? Now that we’re in PowerShell land we can use remoting to promote a DC without logging on. The new Server Manager GUI uses this same technique.
PS C:\> Get-Command -Module ADDSDeployment | ft Name
Name
----
Add-ADDSReadOnlyDomainControllerAccount
Install-ADDSDomain
Install-ADDSDomainController
Install-ADDSForest
Test-ADDSDomainControllerInstallation
Test-ADDSDomainControllerUninstallation
Test-ADDSDomainInstallation
Test-ADDSForestInstallation
Test-ADDSReadOnlyDomainControllerAccountCreation
Uninstall-ADDSDomainController
Change control. Can’t live with it. Can’t live without it.
Scripting a change control is handy for several reasons:
- If your shop has a separate implementation team, then you know they should execute it precisely.
- You can test it in a lab, and then do it the same way in production.
- You know exactly what changed.
- You don’t have to worry about missing a step at 3AM.
Generally change controls have three plans:
- Implementation
- Validation
- Back-Out
You have all three of these scripts for DCPROMO in today’s post. Read through the scripts and the comments to see how easy it can be.
Script Overview
The DCPROMO implementation script hinges on three key cmdlets:
- Install-WindowsFeature
- Invoke-Command
- Install-ADDSDomainController
First, we install the role for Active Directory Domain Services using the ComputerName parameter. Next we use Invoke-Command to remotely execute the DCPROMO with Install-ADDSDomainController. Notice the comments in the code for Invoke-Command. It is really important to understand the $using variable prefix. This little item tripped me up for several hours until a peer reminded me about it. See about_Remote_Variables for the full explanation.
The validation script is short and sweet. It checks for the new AD domain controller object, key services, and the SYSVOL share. Obviously there are many other checks you could add. See the link at the bottom of this post for a great DC validation checklist.
Finally, the back-out script is much like the implementation script, except it calls the uninstall cmdlets in reverse order.
Implementation
# Prompt for credentials to reuse throughout the script
$cred = Get-Credential Cohovineyard\Administrator
# Echo the date for reference in the console output
Get-Date
# Query the current list of domain controllers before the new one
Get-ADDomainController -Filter * |
Format-Table Name, Site, IPv4Address -AutoSize
# Import the module containing Get-WindowsFeature
Import-Module ServerManager
# List the currently installed features on the remote server
Get-WindowsFeature -ComputerName cvmember1.cohovineyard.com |
Where-Object Installed | Format-Table Name
# Install the role for AD-Domain-Services
Install-WindowsFeature –Name AD-Domain-Services `
–ComputerName cvmember1.cohovineyard.com `
-IncludeManagementTools
# List the currently installed features on the remote server
# Notice AD-Domain-Services is now in the list
Get-WindowsFeature -ComputerName cvmember1.cohovineyard.com |
Where-Object Installed | Format-Table Name
# Promote a new domain controller in the existing domain
# Adjust the parameters to meet your own needs
# Notice we're going to handle the reboot ourselves
##### BIG THING TO NOTICE #####
# Notice that the -Credential parameter variable is prefaced with "$using:".
# This is a PS v3 feature, and it is required when passing variables
# into a remote session. Invoke-Command is based on PowerShell remoting.
# Any other parameters that you turn into variables will need "$using:".
Invoke-Command –ComputerName cvmember1.cohovineyard.com –ScriptBlock {
Import-Module ADDSDeployment;
Install-ADDSDomainController `
-NoGlobalCatalog:$false `
-CreateDnsDelegation:$false `
-CriticalReplicationOnly:$false `
-DatabasePath "C:\Windows\NTDS" `
-DomainName "CohoVineyard.com" `
-InstallDns:$true `
-LogPath "C:\Windows\NTDS" `
-NoRebootOnCompletion:$true `
-ReplicationSourceDC "CVDC1.CohoVineyard.com" `
-SiteName "Ohio" `
-SysvolPath "C:\Windows\SYSVOL" `
-Force:$true `
-Credential $using:cred `
-Confirm:$false `
-SafeModeAdministratorPassword `
(ConvertTo-SecureString 'P@ssw0rd' -AsPlainText -Force)
}
# We are going to manage the restart ourselves.
Restart-Computer cvmember1.cohovineyard.com `
-Wait -For PowerShell -Force -Confirm:$false
# Once fully restarted and promoted, query for a fresh list of DCs.
# Notice our new DC in the list.
Get-ADDomainController -Filter * |
Format-Table Name, Site, IPv4Address -AutoSize
# Echo the date and time for job completion.
Get-Date
Validation
Import-Module ActiveDirectory
# Query the current list of domain controllers
Get-ADDomainController -Filter * |
Format-Table Name, Site, IPv4Address -AutoSize
# Check random services common to DCs
Get-Service adws,kdc,netlogon,dns -ComputerName cvdc1
# Check for presence of SYSVOL
Test-Path \\cvdc1\SYSVOL
Back-Out
# Prompt for credentials to reuse throughout the script
$cred = Get-Credential Cohovineyard\Administrator
# Echo the date for reference in the console output
Get-Date
# Query the current list of domain controllers before the removal
Get-ADDomainController -Filter * |
Format-Table Name, Site, IPv4Address -AutoSize
# Reset the error variable
$error.Clear()
# Remove the domain controller in the existing domain
##### BIG THING TO NOTICE #####
# Notice that the -Credential parameter variable is prefaced with "$using:".
# This is a PS v3 feature, and it is required when passing variables
# into a remote session. Invoke-Command is based on PowerShell remoting.
# Any other parameters that you turn into variables will need "$using:".
Invoke-Command –ComputerName cvmember1.cohovineyard.com –ScriptBlock {
Uninstall-ADDSDomainController -Confirm:$false `
-LocalAdministratorPassword `
(ConvertTo-SecureString 'P@ssw0rd' -AsPlainText -Force) `
-DemoteOperationMasterRole:$true `
-Credential $using:cred `
-Force:$true
}
# Exit if the uninstall was unsuccessful
If ($error) {break}
# Give the server time to go down
Start-Sleep -Seconds 5
# The DC removal also removes the host A record in DNS.
# This effectively disables any other remoting until the server reboots.
# Therefore we tell the Uninstall to do the reboot by omitting the
# switch -NoRebootOnCompletion, and then we loop until we can confirm
# the server is reachable again and services are started.
Do { Start-Sleep -Seconds 1 }
Until (Get-CIMInstance Win32_Bios `
-ComputerName cvmember1.cohovineyard.com `
-ErrorAction SilentlyContinue)
# Uninstall the AD DS & DNS roles
Import-Module ServerManager
Uninstall-WindowsFeature `
–Name AD-Domain-Services, DNS, RSAT-AD-Tools, RSAT-AD-PowerShell `
–ComputerName cvmember1.cohovineyard.com `
-IncludeManagementTools `
-Confirm:$false
# Restart the server and wait for services to come back up
Restart-Computer cvmember1.cohovineyard.com `
-Wait -For PowerShell -Force -Confirm:$false
# View the roles to verify that AD-Domain-Services is really gone
Get-WindowsFeature -ComputerName cvmember1.cohovineyard.com |
Where-Object Installed | Format-Table Name
# Query for a fresh list of DCs. Confirm it is gone from the list.
Get-ADDomainController -Filter * |
Format-Table Name, Site, IPv4Address -AutoSize
# Echo the date and time for job completion.
Get-Date
Script Notes
Like other demo scripts I’ve posted there is plenty of room for improvement. Consider these key opportunities regarding the scripts above:
- The functionality in these scripts requires Windows 8 with RSAT or Windows Server 2012.
- Be sure to adjust the values for the parameters on the cmdlets that do all of the heavy lifting.
- Use Read-Host to prompt for the password instead of embedding it in plain text.
- Add a Start-Transcript and Stop-Transcript for logging your activity.
- End the script with a Send-MailMessage that attaches the transcript in an email to you.
- You can swap out all of the hard-coded computer names with variables to make it more reusable.
- You could promote the DC from your smartphone with one hand tied behind your back.
- You could schedule the script to run at 3AM while you are nestled in bed.
Download the full code from the TechNet Script Gallery.
Related Articles
See this TechNet article for the complete textbook explanation of promoting a new DC in Windows Server 2012:
Install a Replica Windows Server 2012 Domain Controller in an Existing Domain (Level 200)
My buddies over at the AskPFEPlat blog have a great checklist for introducing and removing DCs. Use this list to build your own robust validation script:
First, Do No Harm
Another buddy on AskPFEPlat has written a great article for your first 2012 DC:
Introducing the first Windows Server 2012 Domain Controller (Part 1 of 2)
Comments
Anonymous
May 10, 2013
Great tools again from you, Thanks!Anonymous
October 23, 2013
Note if you cut and paste this code block, check the formatting for the newline grave: ` ChrisAnonymous
March 27, 2014
awesome stuff
great blog
Thanks again a fan:)Anonymous
October 03, 2014
The comment has been removedAnonymous
October 07, 2014
The comment has been removedAnonymous
October 07, 2014
The comment has been removedAnonymous
October 29, 2014
Welcome! Today’s post includes demo scripts and links from the Microsoft Virtual Academy event: Using PowerShell for Active Directory . We had a great time creating this for you, and I hope you will share it with anyone needing to ramp up theirAnonymous
August 30, 2017
Thanks for this guide!