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."