Option Explicit

Const    LOG_FILE  = "Set IP Address.txt"

Dim fso        		: Set fso = CreateObject("Scripting.FileSystemObject")
Dim WSHShell   		: Set WshShell = CreateObject("WScript.Shell")
Dim WshNetwork 		: Set WshNetwork = CreateObject("WScript.Network")
Dim oDic       		: Set oDic = CreateObject("Scripting.Dictionary")
Dim objArgs    		: Set objArgs = WScript.Arguments
Dim oSystemEnv 		: Set oSystemEnv = WshShell.Environment("SYSTEM")
Dim oProcessEnv   	: Set oProcessEnv = WshShell.Environment("PROCESS")	
Dim sIPAddress, arrCurrentIPAddress, sSubnetMask, sPrimaryDNS, sSecondaryDNS, sDataFile
Dim sPrimaryWINS, sSecondaryWINS, sDefaultGateway, sDNSSuffix, sSubNetIdentifier, sPingHost
Dim arrTEMP, strBoxToPing, sResultData, sMACAddress, iReturnCode, sLogFile, sNetwork

sLogFile = LOG_FILE

If objArgs.Count = 0 Then
	WScript.echo "ERR: You need to parse the name of the input file!" & vbCRLF & vbCRLF & "     eg: " & wscript.ScriptName & " mydatafile.txt"
    WScript.Quit(1)
End If

sDataFile = objArgs(0)

AppendtoLogFile "" 
AppendtoLogFile TAB & SCRIPT_OPENING_STRING & " (" & wscript.ScriptFullName & " - Ver. " & THIS_SCRIPT_VERSION & ")"
AppendtoLogFile TAB & "Data File      = " & sDataFile

GetAddressInformation
AppendtoLogFile TAB & "MAC Address    = " & sMACAddress
AppendtoLogFile TAB & "Subnet Mask    = " & sSubnetMask
AppendtoLogFile TAB & "Network        = " & sNetwork


If Not fso.FileExists(sDataFile) Then
    AppendtoLogFile ERROR_STR & "Data file not found - " & Chr(34) & sDataFile & Chr(34) 
    wscript.Quit (0)
end If

sPingHost = GetINI(sDataFile,"General","Ping Target","",iReturnCode)
if sPingHost = "" then
    AppendtoLogFile ERROR_STR & "No Ping Target specified in the data file"
    wscript.Quit (0)
End If
AppendtoLogFile TAB & "Ping Target    = " & sPingHost

sIPAddress = GetINI(sDataFile,"IP Address",sMACAddress,"",iReturnCode)
if sIPAddress = "" then
    AppendtoLogFile TAB & "No IP Address information found in the data file. Leaving IP Address information unchanged."
    wscript.Quit (0)
Else
    AppendtoLogFile TAB & "New IP Address = " & sIPAddress
End If
if Instr(sIPAddress,".") = 0 Then
    AppendtoLogFile ERROR_STR & "Bad IP address - terminating"
    wscript.Quit (1)
End If

AppendtoLogFile TAB & "Getting settings for this Network segment"
sDefaultGateway=GetINI(sDataFile,sNetwork,"Default Gateway","",iReturnCode)
if iReturnCode = 2 Then
    AppendtoLogFile ERROR_STR & "Network is not listed in data file - terminating"
    wscript.Quit (1)
End If

sSubnetMask=GetINI(sDataFile,sNetwork,"Subnet Mask","",iReturnCode)
sPrimaryDNS=GetINI(sDataFile,sNetwork,"Primary DNS","",iReturnCode)
sSecondaryDNS=GetINI(sDataFile,sNetwork,"Secondary DNS","",iReturnCode)
sPrimaryWINS=GetINI(sDataFile,sNetwork,"Primary WINS","",iReturnCode)
sSecondaryWINS=GetINI(sDataFile,sNetwork,"Secondary WINS","",iReturnCode)
sDNSSuffix=GetINI(sDataFile,sNetwork,"DNS Suffix","",iReturnCode)

if sDefaultGateway = "" Then
    AppendtoLogFile ERROR_STR & "Bad Default Gateway - terminating"
    wscript.Quit (1)
End if
if sSubnetMask = "" Then
    AppendtoLogFile ERROR_STR & "Bad Subnet Mask - terminating"
    wscript.Quit (1)
End if

RunNetSh

'Now test that we can still communicate

wscript.Sleep(5000) ' Wait 5 seconds for the network connection to settle

if Ping(sPingHost) then 
    AppendtoLogFile(TAB & TAB & "Connection to " & sPingHost & " verified")
    iReturnCode = 0
else
    AppendtoLogFile("### ERROR : Cannot communicate with " & sPingHost & " reverting back to DCHP")
    EnableDHCP
    iReturnCode = 1
    wscript.Sleep(1000)
end if

AppendtoLogFile("    " & SCRIPT_CLOSING_STRING) 
WScript.Quit iReturnCode

' --------------------------------------------------------------------------------------

Sub RunNetSh
   Dim retcode
   AppendtoLogFile(TAB & TAB & "IP Address            = " + sIPAddress)
   AppendtoLogFile(TAB & TAB & "Subnet Mask           = " + sSubnetMask)
   AppendtoLogFile(TAB & TAB & "Default Gateway       = " + sDefaultGateway)
   AppendtoLogFile(TAB & TAB & "Primary WINS Server   = " + sPrimaryWINS)
   AppendtoLogFile(TAB & TAB & "Secondary WINS Server = " + sSecondaryWINS)
   AppendtoLogFile(TAB & TAB & "Primary Name Server   = " + sPrimaryDNS)
   AppendtoLogFile(TAB & TAB & "Secondary Name Server = " + sSecondaryDNS)
   AppendtoLogFile(TAB & TAB & "DNS Suffix            = " + sDNSSuffix)
   
   retcode=WshShell.Run ("netsh interface ip set address ""Local Area Connection"" static " & sIPAddress & " " & sSubnetMask & " " & sDefaultGateway & " 1",0,TRUE)
   if retcode <> 0 then
       AppendtoLogFile(TAB & TAB & "Call to NETSH to set standard IP settings returned " & retcode & " = FAILURE")
   Else
       AppendtoLogFile(TAB & TAB & "Call to NETSH to set standard IP settings returned " & retcode & " = SUCCESS")       
   End If
   retcode=WshShell.Run ("netsh interface ip set wins ""Local Area Connection"" static " & sPrimaryWINS,0,TRUE)
   if retcode <> 0 then
       AppendtoLogFile(TAB & TAB & "Call to NETSH to set primary WINS server returned   " & retcode & " = FAILURE")
   Else
       AppendtoLogFile(TAB & TAB & "Call to NETSH to set primary WINS server returned   " & retcode & " = SUCCESS")       
   End If
   if sSecondaryWINS <> "" then
	  retcode=WshShell.Run ("netsh interface ip add wins ""Local Area Connection"" " & sSecondaryWINS & " index=2",0,TRUE)
	  if retcode <> 0 then
	      AppendtoLogFile(TAB & TAB & "Call to NETSH to set secondary WINS server returned " & retcode & " = FAILURE")
	  Else
	      AppendtoLogFile(TAB & TAB & "Call to NETSH to set secondary WINS server returned " & retcode & " = SUCCESS")       
	  End If
   End if
   retcode=WshShell.Run ("netsh interface ip set dns ""Local Area Connection"" static " & sPrimaryDNS,0,TRUE)
   if retcode <> 0 then
       AppendtoLogFile(TAB & TAB & "Call to NETSH to set primary DNS server returned   " & retcode & " = FAILURE")
   Else
       AppendtoLogFile(TAB & TAB & "Call to NETSH to set primary DNS server to returned   " & retcode & " = SUCCESS")       
   End If
   if sSecondaryDNS <> "" then
       retcode=WshShell.Run ("netsh interface ip add dns ""Local Area Connection"" " & sSecondaryDNS & " index=2",0,TRUE)
       if retcode <> 0 then
           AppendtoLogFile(TAB & TAB & "Call to NETSH to set secondary DNS server returned " & retcode & " = FAILURE")
       Else
           AppendtoLogFile(TAB & TAB & "Call to NETSH to set secondary DNS server returned " & retcode & " = SUCCESS")       
       End If
   End if
   WSHShell.RegWrite "HKLM\System\CurrentControlSet\Services\TCPIP\Parameters\SearchList", sDNSSuffix, "REG_SZ"
   'Note Ref: Q275553 The Netsh utility has no command to set or to change the domain suffix search list.
End Sub

' --------------------------------------------------------------------------

Function AppendtoLogFile(str)
   Const MAX_RETRIES = 3
   Dim f, iRetries
   iRetries=0
   Err.Clear
   'On Error Resume Next
   Do
       Set f = fso.OpenTextFile(sLogFile, FOR_APPENDING, True)
       if err.Number <> 0 then 
           sleep 200
           iRetries=iRetries+1
       end if
   Loop Until (err.Number = 0) or (iRetries => MAX_RETRIES)         
   if err.Number = 0 then
       f.Writeline FormatDateTime(Now,0) + "  " + str
       f.Close
   end if    
   On Error Goto 0
   AppendtoLogFile=err.Number
End Function

' --------------------------------------------------------------------------

Function GetAddressInformation
	Dim aIPConfig, iNICIndex
	aIPConfig  = GetIPConfiguration
	iNICIndex = GetActiveNIC(aIPConfig)
	sMACAddress = aIPConfig(2,iNICIndex)
	sSubnetMask = aIPConfig(1,iNICIndex)
	sNetwork = FindNetworkAddress(aIPConfig(0,iNICIndex),aIPConfig(1,iNICIndex)) & MaskToSlashedNotation(aIPConfig(1,iNICIndex))

End Function

' --------------------------------------------------------------------------

Function GetIPConfiguration
	Dim objWMIService, objSet, obj, i
	On Error Resume Next
	Set objWMIService = GetObject("winmgmts:\\" & "." & "\root\cimv2")
	Set objSet = objWMIService.ExecQuery("select * from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE",,48)
	ReDim aResult(4,-1)
	for each obj in objSet
		if Not IsNull(obj.IPAddress) then 
			for i=LBound(obj.IPAddress) to UBound(obj.IPAddress)
				if obj.IPAddress(i) <> "0.0.0.0" Then
					ReDim Preserve aResult(UBound(aResult,1),UBound(aResult,2) + 1)
    				aResult(0,UBound(aResult,2)) = obj.IPAddress(i)
    				aResult(1,UBound(aResult,2)) = obj.IPSubnet(i)
    				aResult(2,UBound(aResult,2)) = Replace(obj.MACAddress,":","-")
    				aResult(3,UBound(aResult,2)) = Replace(obj.Description,":","")
    				aResult(4,UBound(aResult,2)) = obj.DNSDomain
				End if
			next
		end If
	Next
	On Error Goto 0
    GetIPConfiguration=aResult
End Function

' --------------------------------------------------------------------------

Function GetActiveNIC(aNICData)
	Dim iI, sIPAddress
	For iI = LBound(aNICData,2) To UBound(aNICData,2)
		GetActiveNIC  = iI
		sIPAddress = aNICData(0,iI)
		If (sIPAddress <> "") And (sIPAddress <> "0.0.0.0") And (Left(sIPAddress,3) <> "169") Then : Exit For
	Next
End Function

' --------------------------------------------------------------------------

Function GetINI(str_FileName,str_SectionName,str_ItemName, sDefault, iReturn)
   'iReturn : 1 = File not found
   '             2 = Section not found
   '             3 = Item not found   
   Dim sTEMP, myFile, strFileName, strSectionName, strItemName
   
   iReturn=0   
   strFileName=str_FileName
   strSectionName=str_SectionName
   strItemName=str_ItemName
   GetINI = sDefault
   
   strFileName=trim(strFileName)
   strSectionName=trim(strSectionName)
   strItemName=trim(strItemName)

   if left(strSectionName,1) <> "[" then
       strSectionName="[" + strSectionName
   end if 

   if right(strSectionName,1) <> "]" then
       strSectionName=strSectionName + "]"
   end if 

   if not fso.fileexists(strFileName) then
      iReturn = 1
      Exit Function
   end if 

   Set MyFile = fso.OpenTextFile(strFileName, FOR_READING)
   'Detect Empty File
   if myfile.AtEndOfStream  Then
       MyFile.Close
       Exit Function  
   end if
   Do
       sTEMP = Trim(MyFile.ReadLine)
       if left(sTEMP,1) = ";" then          ' ignore a line that start with a ";"
          sTEMP=""
       end if
   Loop Until myfile.AtEndOfStream or (Instr(UCase(sTEMP),UCase(strSectionName)) = 1) 

   if myfile.AtEndOfStream Then
     iReturn = 2
     MyFile.Close
     Exit Function 
   end if      
   
   Do
       sTEMP = Trim(MyFile.ReadLine)
       if left(sTEMP,1) = ";" then          ' ignore a line that start with a ";"
          sTEMP=""
       end if
       if instr(UCase(sTEMP),"[") = 1 then  ' Start of next section
           iReturn = 3
           MyFile.Close
           Exit Function        
       end if
   Loop Until myfile.AtEndOfStream or (Instr(UCase(sTEMP),UCase(strItemName)) = 1)  

   MyFile.Close
   
   If (Instr(UCase(sTEMP),UCase(strItemName)) <> 1) Then
       iReturn = 3
       Exit Function    
   End if 
 
   sTEMP=trim(right(sTEMP,len(sTEMP) - (InStr(sTEMP,"="))))
          
   if instr(sTEMP,";") <> 0 then           ' Check for "on the line" comments
       sTEMP=trim(left(sTEMP,instr(sTEMP,";")-1))
   end if
   
   if sTEMP <> "" then : GetINI=sTEMP
end function    

' --------------------------------------------------------------------------

Function FindNetworkAddress (IPAddress, SubnetMask)
	Dim subnetoctets, ipaddroctets
    subnetoctets = split(SubnetMask, ".", 4)
    ipaddroctets = split(IPAddress, ".", 4)
    FindNetworkAddress = join(Array(ipaddroctets(0) and subnetoctets(0), ipaddroctets(1) and subnetoctets(1), _
        				ipaddroctets(2) and subnetoctets(2), ipaddroctets(3) and subnetoctets(3)),".")
End Function

' --------------------------------------------------------------------------

Function MaskToSlashedNotation(sMask)
	Dim table, aSubnetOctets
	table = Array( _
	0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, _
	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, _
	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, _
	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, _
	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, _
	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, _
	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, _
	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8) 
  	aSubnetOctets = split(sMask, ".", 4)
	MaskToSlashedNotation = "/" & (table(aSubnetOctets(0)) + table(aSubnetOctets(1)) + table(aSubnetOctets(2)) + table(aSubnetOctets(3)))
End Function

' --------------------------------------------------------------------------

Function Ping(sHostName)
	Dim objWMIService, colPings, objStatus
	Set objWMIService = GetObject("winmgmts:\\" & "." & "\root\cimv2")
	Set colPings = objWMIService.ExecQuery("Select * From Win32_PingStatus where Address = '" & sHostName & "'") 
	For Each objStatus in colPings
		If IsNull(objStatus.StatusCode) Or (objStatus.StatusCode <> 0) Then 
			Ping = False
		Else
			Ping = True
		End If
	Next 
End Function

' --------------------------------------------------------------------------

Function EnableDHCP
    ' 
    ' This function sets all network adapters to use DCHP
    '
	Dim aDNSServers, objWMIService, colNetAdapters, objNetAdapter, errDNSServers, errWINS, errEnable
	EnableDHCP = False
	aDNSServers = Array()
	Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
	Set colNetAdapters = objWMIService.ExecQuery ("Select * from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE")
	For Each objNetAdapter In colNetAdapters
		errDNSServers = objNetAdapter.SetDNSServerSearchOrder(Array())  'Clear DNS Servers
		errWINS = objNetAdapter.SetWINSServer("","")                    'Clear WINS Servers
		errEnable = objNetAdapter.EnableDHCP()
		If errEnable = 0 Then : EnableDHCP = True
	Next
End Function	

' --------------------------------------------------------------------------

Const           THIS_SCRIPT_VERSION = "2.2"
Const         SCRIPT_OPENING_STRING = "Begin setting static IP address information"
Const         SCRIPT_CLOSING_STRING = "Completed setting static IP address information"
Const                          TAB  = "    "
Const                    ERROR_STR  = "### ERROR "
Const                  FOR_READING  =  1
Const                 FOR_WRITTING  =  2
Const                FOR_APPENDING  =  8
Const         TRISTATE_USE_DEFAULT  = -2 'Opens the file using the system default.
Const                TRISTATE_TRUE  = -1 'Opens the file as Unicode.
Const               TRISTATE_FALSE  =  0 'Opens the file as ASCII.




