Easily change DNS servers for computers with static IP addresses using PowerShell. Run locally or remote.
Changing DNS servers
Recently I provisioned new domain controllers as part of a migration from a 2008 R2 Active Directory forest to a 2016 Active Directory forest. Like the existing 2008 R2 domain controllers, the new domain controllers are configured as AD integrated DNS servers and will be the primary and secondary DNS servers used on the internal network.
Changing DNS servers for clients using DHCP is a trivial matter; just update Option 6 for the DHCP scope with the new name server IP addresses and restart the client (or wait until they renew their lease).
However if you are like a lot of environments, you have Windows servers and maybe even workstations configured with static IP addresses and static DNS servers. How can you systematically update these configurations?
Change DNS servers with Win32_NetworkAdapterConfiguration
We can use PowerShell and Get-WmiInstance or Get-CimInstance (Win 8/2012 or later). For compatibility, we will be demonstrating using Get-WmiInstance.
In our scenario, our old DNS servers were 192.168.1.11 and 192.168.1.12. We will be replacing these with 192.168.1.13 and 192.168.1.14. We use the following snippet leveraging the class Win32_NetworkAdapterConfiguration to return a list of all non-DHCP adapters with DNS servers configured.
$Adapters = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.DHCPEnabled -ne 'True' -and $_.DNSServerSearchOrder -ne $null}
To see the current DNS servers, we run the following:
PS C:\Windows\system32> $Adapters | ForEach-Object {$_.DNSServerSearchOrder} 192.168.1.11 192.168.1.12
To update the DNS servers for adapters meeting this criteria, we run the following:
$NewDnsServerSearchOrder = "192.168.1.13","192.168.1.14" $Adapters | ForEach-Object {$_.SetDNSServerSearchOrder($NewDnsServerSearchOrder)} | Out-Null
To confirm the servers have been updated, re-run our original Get sequence:
$Adapters = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.DHCPEnabled -ne 'True' -and $_.DNSServerSearchOrder -ne $null} PS C:\Windows\system32> $Adapters | ForEach-Object {$_.DNSServerSearchOrder} 192.168.1.13 192.168.1.14
Remotely updating DNS servers for set of computers
The previous section covered the basic updating of the DNS servers locally on a single computer. However you may have the need to update multiple computers remotely.
One approach would be to query your Active Directory to get a list of all computers that have statically assigned IP addresses. For example, it may be that all of your computers running a Windows Server OS have static IPs.
Get all “Windows Server” AD computers
We can get all of the the computers in Active Directory that are running a “Windows Server” build using the following Get-ADComputer query:
$Computers = Get-ADComputer -Filter '(OperatingSystem -like "Windows Server*")' | Sort-Object Name
Use Invoke-Command to update DNS on remote computers
We now have a set of computers to process. We will use Invoke-Command to connect via WinRM to the remote computer and execute the previous commands locally on the computer.
ForEach ($Computer in $Computers) { Write-Host "$($Computer.Name): " -ForegroundColor Yellow Invoke-Command -ComputerName $Computer.Name -ScriptBlock { $NewDnsServerSearchOrder = "192.168.1.13","192.168.1.14" $Adapters = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.DHCPEnabled -ne 'True' -and $_.DNSServerSearchOrder -ne $null} # Show DNS servers before update Write-Host "Before: " -ForegroundColor Green $Adapters | ForEach-Object {$_.DNSServerSearchOrder} # Update DNS servers $Adapters | ForEach-Object {$_.SetDNSServerSearchOrder($NewDnsServerSearchOrder)} | Out-Null # Show DNS servers after update $Adapters = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.DHCPEnabled -ne 'True' -and $_.DNSServerSearchOrder -ne $null} Write-Host "After: " -ForegroundColor Green $Adapters | ForEach-Object {$_.DNSServerSearchOrder} } }
Why we used Invoke-Command
We could use the WMI cmdlets directly against the remote computer, but it would require all of the necessary network port access and permissions for using WMI remotely. Connecting using WinRM only requires a single network port to be opened and lets us run all other cmdlets without having to give a lot of thought to remote security and performance over the network.
Set-DnsClientServerAddress: Windows 8/2012 or newer
The method described above is intended for maximum compatibility: it will work with Windows Server 2003 all the way through Windows Server 2016. If however your environment is running Windows 8 / Windows Server 2012 and above, you do not need to use the WMI cmdlets, you can use the newer cmdlet Set-DnsClientServerAddress.
Set-DnsClientServerAddress -InterfaceIndex 2 -ServerAddresses ("192.168.1.13","192.168.1.14")
Note that we specified the InterfaceIndex. Other interface identification options are InterfaceAlias or you can pass a CimInstance for an interface to the cmdlet. You could use this cmdlet in hybrid with our previous Get-WmiObject query:
$Adapters = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.DHCPEnabled -ne 'True' -and $_.DNSServerSearchOrder -ne $null} $Adapters | Set-DnsClientServerAddress -ServerAddresses "192.168.1.13","192.168.1.14"
Conclusion
Using this approach as a starting point, you can modify as required fit your own environment’s requirements to confidently and efficiently update DNS servers for computers with statically assigned IPs.