Migrating from Windows Server 2012 R2 to Windows Server 2016

As a first step to migrate an old windows server to a new Windows Server 2016, it is always better to chalk out a strategy or a check list. This will help ensure no hiccups come in between the process.

In this direction, the first step can be listing out the roles and features installed on the server. At this stage we would also identify the things that will not automatically come to the new server once it is brought into the domain and promoted.

In my example I am considering a server “server1” installed with Windows Server 2012 R2. It is an additional domain controller and also has DNS and DHCP roles installed in it. “server1” is in a DHCP failover relation (Hot Standby) with another DC “server2”.

Following are the things that we need to manually configure in the new server and is painstaking.

1> During roles and features installation stage, we need to manually install the same.

2> Conditional Forwarders (if any) configured at server level.

3> DHCP server level configurations.

4> IP configuration which in this case will be same as the old one.

Now we will one by one try to automate these steps. There sure are other ways to do this like command line approach and GUI, but will restrict ourselves to powershell here.

1> We can perform below steps to automate the installation of roles and features, which can take time to select all roles and features and can lead to errors also.

First, using PowerShell, we need to create an answer file from already existing server “server1”, containing list of all roles and features installed.

Get-WindowsFeature |
? { $_.Installed -AND $_.SubFeatures.Count -eq 0 } |
Export-Clixml \\server3\c$\ServerFeatures.xml

Second, from elevated PowerShell, we will import the same answer file in the new server “server3” and it will automatically install all the roles and features in that file.

$ServerFeatures = Import-Clixml c:\ServerFeatures.xml
foreach ($feature in $ServerFeatures) {
Install-WindowsFeature -Name $feature.name

2> We can make use of a powershell module DnsShell to export DNS conditional forwarders from “server1” to “server3”. First we should download the module which is compatible with powershell version 4.0 also and then importing it as follows.

import-module "C:\Program Files (x86)\WindowsPowerShell\Modules\DnsShell"

For making the module available to all the users logging into the system, the module should be placed in “C:\Program Files (x86)\WindowsPowerShell\Modules\”

Get-DnsZone -ZoneType Forwarder -Server server1 | New-DnsZone -Server server3

In this way we are piping the DNS conditional forwarders settings to the new server in one command.

3> Now we will look into transfering the server level configurations that we might have on the olde server “server1”. We will first execute below command in powershell to create a backup of DHCP leases.

export-dhcpserver -computername server1 -file "c:\dhcpexport.xml" -leases

Then we can import this exported file in new server either by specifying UNC path of file or by first manually copying the file in new location. Kindly note that we need to specify here the DHCP backup directory which can be seen in properties of dhcp server in DHCP console.

Import-DhcpServer -ComputerName server2 -File C:\dhcpexport.xml -BackupPath C:\dhcpbackup\ -ServerConfigOnly

We need not export other configurations as the old server “server1” is in a DHCP failover relation with “server2”. Hence when we reconfigure the failover between “server2” and “server3”, complete configuration will get replicated to the new server “server3” except the server level configuration. We can refer to this link for setting up a DHCP failover.

4> Before the old server “server1” has been demoted, unjoined from domain and shutdown permanently, we should export the IP configuration of the server and store in a migration store folder.

Export-SmigServerSetting -IPConfig -Path "c:\ipexport\" -Verbose

Also it would be better if we export the IP configuration to a text file from command line.

IPConfig -all >  c:\ipconfig.txt

Now we can import the configuration in the new server “server3” by first copying both the “ipconfig.txt” and migration store folder to the new server “server3” and then executing below command in powershell. We need to perform this step only when the old server “server1” is completely removed. Also we must know the MAC addresses of the source and destination NIC cards.

Import-SmigServerSetting -IPConfig All -SourcePhysicalAddress "XX-XX-XX-XX-XX-XX" -TargetPhysicalAddress "YY-YY-YY-YY-YY-YY" -Path "c:\ipexport\" -Verbose

For detailed ip configuration migration steps, we can refer to this technedt link IP Configuration: Migrating IP Configuration Data

This concludes our discussion here.


Working with DHCP failover information in a Windows Server 2012 environment

In this article, we will discuss about a method to get the information regarding DHCP failover configuration in our domain and the corresponding DHCP servers names (Primary and Secondary). Along with DHCP servers Names, we would also get information such as  Scope ID, Subnet mask, Start and End range. All this data collected would then be appended to a csv file.

A point to be noted here is that prior to windows server 2012, DHCP failover could only be possible in a Windows server based cluster environment, But going further with windows server 2012, DHCP failover can be very easily configured from DHCP console between two nodes. Step-by-Step: Configure DHCP for Failover This link gives a background of what i mentioned here along with some more information. Therefore following discussion will be applicable only for Windows Server 2012 setups or newer.

[threading.thread]::CurrentThread.CurrentCulture = 'en-US'
$CurrentDate = Get-Date -format dddd
$CSVFile = "C:\Dhcp_report_$CurrentDate.csv"
$machines = Get-DhcpServerInDC

"DHCPServer,SecondaryDHCPServer,ScopeName,ScopeID,Subnetmask,Startrange,Endrange" |out-file -FilePath $CSVFile -append

foreach ($machine in $machines)
$DHCPName = $machine.dnsname
if ($DHCPName -notin @("server01.company.corp","server02.company.corp")){
$AllScopes = Get-DhcpServerv4Scope -ComputerName $DHCPName
foreach ($scope in $AllScopes)
$ScopeName = $scope.Name
$ScopeId = $scope.ScopeId
$failoverscope = Get-dhcpserverv4failover -ComputerName $DHCPName -ScopeId $ScopeId -ErrorAction SilentlyContinue
if ($failoverscope) {
$SecDHCP = ($failoverscope.SecondaryServerName)
else {
$SecDHCP = "no failover"
$Subnetmask = $scope.subnetmask
$Startrange = $scope.startrange
$Endrange = $scope.endrange
$OutInfo = ($DHCPName).Replace(".company.corp","") + "," + ($SecDHCP).Replace(".company.corp","") + "," +$ScopeName + "," + $ScopeId+ "," + $Subnetmask + "," + $Startrange + "," + $Endrange
Write-Host $OutInfo
Add-Content -Value $OutInfo -Path $CSVFile

DHCP Server Cmdlets in Windows PowerShell will give a full list of powershell commands associated with DHCP.

Alerting if a change of failover is detected

Now with the same commands we shall create another script that will first search for all authorised DHCPs in the domain, then it will sequentially scan through a list of servers to see if they are authorised. Also it will see if their is a change of failover state of dhcp from main DHCP to partner DHCP server. Then it will also check if DHCP services are up and running if the main DHCP server’s failover state is active.

We can even insert a code module for sending mails if an unexpected change of failover state has happened. This script could be scheduled in task scheduler to perform this check regularly to avoid any unwanted changes.

$authdhcps=Get-DhcpServerInDC|select dnsname
$machines = get-content "c:\servers.txt"
foreach ($machine in $machines)

if ($authdhcps -match [System.Net.Dns]::GetHostByName("$machine").HostName){
write-host $machine "is authorised dhcp server"
$a=get-dhcpserverv4failover -computername $machine

if ($a.serverrole -eq "Active"){
$p = $a.partnerserver
Write-host "$machine is active and $p is in standby. Now checking DHCP server and client service status."
$dhcpServices = Get-Service -ComputerName $machine -Name *dhcp*

foreach ($dhcpService in $dhcpServices){

if ($dhcpService.Status -eq "Running"){
Start-Service $dhcpService
Write-Host "Starting " $dhcpService.DisplayName " service on $machine"
" ---------------------- "
" Service is now started"

Write-Host $dhcpService.DisplayName "service is already started on $machine"

write-host $machine "is not authorised dhcp server"

Write-host "$machine is standby and now checking if partner server $p is authorised dhcp server"

if ($authdhcps -match [System.Net.Dns]::GetHostByName("$p").HostName){
write-host $p "is authorised dhcp server.Now checking DHCP server and client service status"
$dhcpServices = Get-Service -ComputerName $p -Name *dhcp*

foreach ($dhcpService in $dhcpServices){

if ($dhcpService.Status -eq "Running"){
Start-Service $dhcpService
Write-Host "Starting " $dhcpService.DisplayName " service on $p"
" ---------------------- "
" Service is now started on partner $p"

Write-Host $dhcpService.DisplayName "service is already started on partner $p"

write-host $p "is not authorised dhcp server"

Lastly we can see that there are are two ways by which we can get FQDN or DNS name of a server as can be seen in each of the above two scripts.

First is,

$DHCPName = $machine.dnsname

And second will be,


Another fun thing that can create confusion at many times is that prior to windows server 2012, the service status would be “started” if it is running fine.

Whereas going forward with windows server 2012, the service status would be “running” if it were running.

Please excuse for poor script formatting 🙂