Search This Blog

Tuesday, July 14, 2009

Change DNS on multiple computers

Ok, here is the background. We needed to get rid of some old hardware and replace them with new kit. These servers was DC/DNS and unfortunately we couldn't re-use the IP addresses which meant that all the DNS settings on the servers (the clients used DHCP) needed to get updated.

My client at the time was planning to do this manually, which was not smart at all. Even though their server park was only about 900 servers. So what to do? Obviously scripting was the answer so I put this little script together for them.

Do note that I couldn't get proper formatting (especially TAB) in this post so the script might look a bit strange. Also note that line breaks are not always correct, so test it first in your lab! I take NO responsibility for the script and it is your responsibility to test it in a lab environment!

-Script Begins-
'============================================================
' NAME: replaceDNS_Server.vbs
'
' AUTHOR: Jimmy Andersson, Q Advice AB
' DATE: 19/11/2008
' Version: 1.0 - initial version
'
' COMMENT: Used to replace an IP entry for the DNS settings with a new IP. It will
' do a ping test before trying to connect to the remote machine. Do note that it
' ONLY replaces the IP if it is found, if it can't find the IP nothing will happen
' and it will also return the name of the machine it didn't find it on. If a NIC is
' DHCP ENABLED it will not change anything on that particular NIC.
'
' USAGE: cscript ReplaceDNS_Server.vbs
'
' NOTE: If you don't have access it will just move on to the next one in the list.
' If you want to save the output' pipe it to a text file.
' Example: cscript ReplaceDNS_Server.vbs > output.txt
'============================================================

On Error Resume Next

'============================================================

'====== Specify input file and open it - One computer name per row ========
'============================================================
strFilename = "C:\serverNames.txt"

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTS = objFSO.OpenTextFile(strFilename)

Do Until objTS.AtEndOfStream
strComputer = objTS.ReadLine
DoObject strComputer
Loop
objTS.Close

'============================================================
'====== Sub to replace a DNS entry ================================
'============================================================
Sub DoObject(strComputer)

strOldDNSServer = "10.80.255.122" ' Specify which DNS IP that should be replaced

strNewDNSServer = "10.80.255.206" ' Specify the new DNS IP

' Run ping test before starting to run WMI queries
strPingStatus = PingStatus(strComputer)
If strPingStatus = "Success" Then ' See return codes in the Function

Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

' Only do changes if IP is enabled and DHCP is not used
Set colNicConfigs = objWMIService.ExecQuery _
("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = TRUE AND DHCPEnabled = FALSE")

For Each objNicConfig In colNicConfigs
wScript.Echo VbCrLf & "Computer: " & strComputer
wScript.Echo VbCrLf & " Network Adapter " & objNicConfig.Index
arrDNSServerSearchOrder = objNicConfig.DNSServerSearchOrder

wScript.Echo " DNS Server Search Order - Before:"
If Not IsNull(objNicConfig.DNSServerSearchOrder) Then
For Each strDNSServer In objNicConfig.DNSServerSearchOrder
wScript.Echo " " & strDNSServer
Next
End If

blnFound = 0
For i = 0 to UBound(arrDNSServerSearchOrder)
If arrDNSServerSearchOrder(i) = strOldDNSServer Then
arrDNSServerSearchOrder(i) = strNewDNSServer
blnFound = 1
End If
Next

If blnFound Then
retSetDNS = objNicConfig.SetDNSServerSearchOrder(arrDNSServerSearchOrder)
If retSetDNS = 0 Then
wScript.Echo " Replaced " & strOldDNSServer & " with " & _
strNewDNSServer & " in DNS search order."

Else
wScript.Echo " Unable to change DNS server search order."
End If

Else
WScript.Echo " DNS server " & strOldDNSServer & " not found."
End If
Next

Set colNicConfigs = objWMIService.ExecQuery _
("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = TRUE")
For Each objNicConfig In colNicConfigs
wScript.Echo VbCrLf & "Computer: " & strComputer & " -- " & "DHCP Enabled => NO changes done."
wScript.Echo VbCrLf & String(80, "-")
Next

Else
wScript.Echo VBCrLf & "Computer: " & strComputer & " -- " & "Didn't answer ping => NO changes done."

' Return which machines that didn't answered on ping
wScript.Echo VbCrLf & String(80, "-")
End If

End Sub

'============================================================
'====== Function for w32_PingStatus WMI class =======================
'============================================================
Function PingStatus(strComputer)
On Error Resume Next

' Uses the local machine as the system to ping from
strWorkstation = "."


Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strWorkstation & "\root\cimv2")

Set colPings = objWMIService.ExecQuery _
("SELECT * FROM Win32_PingStatus WHERE Address = '" & strComputer & "'")


For Each objPing in colPings ' Return codes
Select Case objPing.StatusCode

Case 0 PingStatus = "Success"
Case 11001 PingStatus = "Status code 11001 - Buffer Too Small"
Case 11002 PingStatus = "Status code 11002 - Destination Net Unreachable"
Case 11003 PingStatus = "Status code 11003 - Destination Host Unreachable"
Case 11004 PingStatus = "Status code 11004 - Destination Protocol Unreachable"
Case 11005 PingStatus = "Status code 11005 - Destination Port Unreachable"
Case 11006 PingStatus = "Status code 11006 - No Resources"
Case 11007 PingStatus = "Status code 11007 - Bad Option"
Case 11008 PingStatus = "Status code 11008 - Hardware Error"
Case 11009 PingStatus = "Status code 11009 - Packet Too Big"
Case 11010 PingStatus = "Status code 11010 - Request Timed Out"
Case 11011 PingStatus = "Status code 11011 - Bad Request"
Case 11012 PingStatus = "Status code 11012 - Bad Route"
Case 11013 PingStatus = "Status code 11013 - TimeToLive Expired Transit"
Case 11014 PingStatus = "Status code 11014 - TimeToLive Expired Reassembly"
Case 11015 PingStatus = "Status code 11015 - Parameter Problem"
Case 11016 PingStatus = "Status code 11016 - Source Quench"
Case 11017 PingStatus = "Status code 11017 - Option Too Big"
Case 11018 PingStatus = "Status code 11018 - Bad Destination"
Case 11032 PingStatus = "Status code 11032 - Negotiating IPSEC"
Case 11050 PingStatus = "Status code 11050 - General Failure"
Case Else PingStatus = "Status code " & objPing.StatusCode & _
" - Unable to determine cause of failure."
End Select
Next

End Function

-Script Ends-

10 comments:

Anonymous said...

nice job. thanks!

Jimmy Andersson [DS MVP] said...

You're welcome, I'm glad if I helped someone!

/Jimmy

Anonymous said...

the ping function in there is word the price of admission alone. good stuff.

Nandish Parmar said...

Hy good job.
Can you suggest me what would need to change, if I want to push this script thru SCCM/GPO.

I believe the strFileName = "C:\ServerNames.txt" has to be changed to LOCALHOST ? Or is there something else I am missing?

Unknown said...

Hi Jimmy really i am very much pleased of this post, thank a lot; really awesome. If possible can you let me know how to change the DNS server ip directly without mentioning the previous DNS server IP as i have to get the DNS server details of all the servers first to change them. also is it possible to change both primary and seconday dns at a time.

Anonymous said...

hey mate is there anyway to force it to change both preferred/alternate regardless of what ip is there

Anonymous said...

Hey RcM:

Take a look at this:
http://www.isrcomputing.com/knowledge-base/programming-tips/112-how-to-change-ip,-gateway-annd-dns-with-vbscript.html

Anonymous said...

Hey Nandish,

Try this:
1. Comment out these lines:

strFilename = "C:\serverNames.txt"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTS = objFSO.OpenTextFile(strFilename)
Do Until objTS.AtEndOfStream

2. Change strComputer = objTS.ReadLine to strComputer = "."

Unknown said...

Awesome Script. it worked for me in wk12 also.

thanks.

Pig Bastard said...

This is an amazing script, many many many thanks.
Tried to accomplish this with wmic, netsh, powershell, but this script it is exactly what I needed and so simple.