Powershell – Set static DNS on remote servers

Standard

Recently I was tasked with the job of changing the DNS search order on all the windows servers we use in my company. Since I didn’t want to change it manually by going into the TCP/IP settings of the NIC on each server I decided to write a script to help me do this.

I am working in a sensitive production environment so I needed to not only change the settings but also check that the changes were made successfully on all servers. To accomplish this I added some functionality to the script to confirm that the changes were made and write all the information to a log file. This log file could then be reviewed later for errors.

I have built the script in three different sections – variables, functions and script main. To begin with I will quickly explain the variables section.

VARIABLES

I don’t like working with too many absolute paths in my scripts because one needs to change them if they are moved to another computer or location. Therefore I use the following code so I always have an object pointing to the script directory.

$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath

When used, $dir will always point to the directory where the script was run. $log_dir specifies the path to a directory names /logs which will be used later on.

The script takes input from a file called “servers.txt” which must be placed in the script directory. $servers is an array created and populated by running Get-Content on “servers.txt”. The parameters section contains the $dns1, $dns2, $dns3 objects which will be set on the servers listed in “servers.txt” – remember to fill these out with the appropriate values before running the script.

#VARIABLES
$DebugPreference = "continue"
$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
$log_dir = "$dir\logs"
$servers = @(gc "$dir\servers.txt")
#parameters - Add the desired DNS servers below
[string]$dns1 = "192.168.1.2"
[string]$dns2 = "192.168.1.3"
[string]$dns3 = "192.168.1.4"

That covers the variables section – now to the functions. The script is built on four different functions which I will go over now.

FUNCTIONS

1. Function Create-Log

function Create-Log {
	$time = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
	$logFilePath = "$log_dir\SetStaticDNS_$time.log"
	New-Item -ItemType File $logFilePath -Force
}
 

This little function simply creates a logfile in $dir\logs\ which will be used by the script to record the results of attempting to change the DNS settings on each server.

2. Function Write-ToLog

function Write-ToLog {
	param (
		[string]$message
		)
	$time = Get-Date
	$logEntryStr = "$time`t" + $message
	$logEntryStr | Out-File -Append $logFilePath -Width 400
}
 

Write-ToLog takes a parameter “message” and appends it to the log file with a time stamp

3. Get-ActiveNicIP

function Get-ActiveNicIP {
 	param (
 		[Parameter(Mandatory=$true)][string]$computer
 	)
 	Write-ToLog -message "Getting IP of 'active' interface on $computer ..."
 	$conx = Test-Connection -ComputerName $computer -Count 1
 	$ActiveIP = $conx.IPV4Address.IPAddressToString
 	Write-ToLog -message "Active IP on $computer is $ActiveIP"
 	return $ActiveIP
}

Some servers can have several NICs/Teams in use and I wanted to make sure that I only change the DNS settings on the NIC which answers to the hostname of the server. Get-ActiveNicIP simply pings the server given as the parameter “computer” and returns the IP which answers.

4. Function Set-StaticDNS

function Set-StaticDNS {
	param (
		[Parameter(Mandatory=$true)][string]$computer,
		[Parameter(Mandatory=$true)][string]$ActiveIP
	)
	Write-ToLog -message "Attempting to set DNS search order on computer 	$computer on the interface with the IP $ActiveIP"
	#get dns info via WMI
	$wmi = Get-WmiObject win32_networkadapterconfiguration -filter "ipenabled = 'true'" -ComputerName $computer | ? { $_.IPAddress -match $ActiveIP }
	#set dns search order via WMI
	$wmi.SetDNSServerSearchOrder($DnsSearchOrder)
	#confirm that dns search order was set to desired value.
	$StrdnsSearchOrder = $dnsSearchOrder | Out-String
	$wmi2 = Get-WmiObject win32_networkadapterconfiguration -filter "ipenabled = 'true'" -ComputerName $computer | ? { $_.IPAddress -match $ActiveIP }
	$StrWmiDnsSearchOrder = $wmi2.DNSServerSearchOrder | Out-String
	if ($StrWmiDnsSearchOrder -eq $StrdnsSearchOrder) {
	Write-ToLog -message "Setting the DNS search order was successful. Value is now $dnsSearchOrder"
	}
	else {
		Write-ToLog -message "Error - Setting the DNS search order failed!"
	}
}

The Set-Static DNS function takes a computer and an IP as parameters and then uses WMI to change the DNS search order on the NIC.
That covers the functions – now to the script main.

SCRIPT MAIN

#SCRIPT MAIN
clear
$dnsSearchOrder = @()
$dnsSearchOrder += @($dns1)
$dnsSearchOrder += @($dns2)
$dnsSearchOrder += @($dns3)
$logFilePath = Create-Log
Write-ToLog -message "Starting script Set-StaticDNS.ps1...."
Write-ToLog -message "Setting DNS search order on all servers in 'servers.txt' to $dnsSearchOrder"
Write-ToLog -message "----------------------------------------------------------------------------------------------------------`n`n"
$servers | % {
	$ActiveIP = Get-ActiveNicIP -computer $_
	Set-StaticDNS -computer $_ -ActiveIP $ActiveIP
}
Write-ToLog -message "`n`n----------------------------------------------------------------------------------------------------------"
Write-ToLog -message "Script run ended."

The script main simply loops through the $servers array and runs the Get-ActiveNipIP and Set-StaticDNS functions on each server.
That should explain how the script works. I have copied in the full script below.
Enjoy!

################################################################################################
##Script:		Set-StaticDNS.ps1
##
##Description:		Sets the DNS search order on the servers given as input in servers.txt
#+			to the IP addresses specified in the parameters section.
##Created by:		Noam Wajnman
##Creation Date: December 9, 2013
################################################################################################
#FUNCTIONS
function Create-Log {
	$time = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
	$logFilePath = "$log_dir\SetStaticDNS_$time.log"
	New-Item -ItemType File $logFilePath -Force
}
function Write-ToLog {
	param (
		[string]$message
	)
	$time = Get-Date
	$logEntryStr = "$time`t" + $message
	$logEntryStr | Out-File -Append $logFilePath -Width 400
}
function Get-ActiveNicIP {
	param (
		[Parameter(Mandatory=$true)][string]$computer
	)
	Write-ToLog -message "Getting IP of 'active' interface on $computer ..."
	$conx = Test-Connection -ComputerName $computer -Count 1
	$ActiveIP = $conx.IPV4Address.IPAddressToString
	Write-ToLog -message "Active IP on $computer is $ActiveIP"
	return $ActiveIP
}
function Set-StaticDNS {
	param (
		[Parameter(Mandatory=$true)][string]$computer,
		[Parameter(Mandatory=$true)][string]$ActiveIP
	)
	Write-ToLog -message "Attempting to set DNS search order on computer $computer on the interface with the IP $ActiveIP"
	#get dns info via WMI
	$wmi = Get-WmiObject win32_networkadapterconfiguration -filter "ipenabled = 'true'" -ComputerName $computer | ? { $_.IPAddress -match $ActiveIP }
	#set dns search order via WMI
	$wmi.SetDNSServerSearchOrder($DnsSearchOrder)
	#confirm that dns search order was set to desired value.
	$StrdnsSearchOrder = $dnsSearchOrder | Out-String
	$wmi2 = Get-WmiObject win32_networkadapterconfiguration -filter "ipenabled = 'true'" -ComputerName $computer | ? { $_.IPAddress -match $ActiveIP }
	$StrWmiDnsSearchOrder = $wmi2.DNSServerSearchOrder | Out-String
	if ($StrWmiDnsSearchOrder -eq $StrdnsSearchOrder) {
		Write-ToLog -message "Setting the DNS search order was successful. Value is now $dnsSearchOrder"
	}
	else {
		Write-ToLog -message "Error - Setting the DNS search order failed!"
	}
}
#VARIABLES
$DebugPreference = "continue"
$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
$log_dir = "$dir\logs"
$servers = @(gc "$dir\servers.txt")
#parameters - Add the desired DNS servers below
[string]$dns1 = "192.168.1.2"
[string]$dns2 = "192.168.1.3"
[string]$dns3 = "192.168.1.4"
#SCRIPT MAIN
clear
$dnsSearchOrder = @()
$dnsSearchOrder += @($dns1)
$dnsSearchOrder += @($dns2)
$dnsSearchOrder += @($dns3)
$logFilePath = Create-Log
Write-ToLog -message "Starting script Set-StaticDNS.ps1...."
Write-ToLog -message "Setting DNS search order on all servers in 'servers.txt' to $dnsSearchOrder"
Write-ToLog -message "----------------------------------------------------------------------------------------------------------`n`n"
$servers | % {
	$ActiveIP = Get-ActiveNicIP -computer $_
	Set-StaticDNS -computer $_ -ActiveIP $ActiveIP
}
Write-ToLog -message "`n`n----------------------------------------------------------------------------------------------------------"
Write-ToLog -message "Script run ended."

6 thoughts on “Powershell – Set static DNS on remote servers

  1. Gracias para todos los demás sitio. El lugar else Mayo Me estoy haciendo que tipo
    de información información escrita de tal un perfecto método forma?
    Tengo empresa Estoy sólo funcionamiento en, y I han sido en la vistazo por tal información .

  2. Antonio Castillo

    I’m trying to run this script, but if the computer has the firewall on, this don’t work, if I disable the firewall before run the script, this work fine, how can handled this issue.?

Leave a reply to noamwajnman Cancel reply