Updating several IP addresses using ADSI

(Note: I had originally posted this information on a blog that I kept on http://weblogs.asp.net, but it makes more sense to post it here. [:)] )

Like many web programmers, I host several hobby web sites for fun. (They make a wonderful test bed for new code. ;-] )

And like many computer enthusiasts, I sometimes change my ISP for one reason or another. If you are hosting web sites in a similar situation, I’m sure that you can identify the pain of trying to manually update each old IP address to your new IP address. This situation can be made even more difficult when any number of your web sites are using several host headers because the user interface for the IIS administration tool only lists the first host header. This means that you have to manually view the properties for every site just to locate the IP addresses that you are required to change.

Well, I'm a big believer in replacing any repetitive task with code when it is possible, and a recent change of ISP provided just the right level of inspiration for me to write a simple Active Directory Service Interfaces (ADSI) script that locates IP addresses that have to be changed and updates them to their new values.

To use the example script, I would first suggest that you make a backup copy of your metabase. (The script works fine, but it is always better to have a backup. ;-] ) As soon as your metabase has been backed up, copy the example script into notepad or some other text editor, update the old and new IP addresses that are defined as constants, and then run the script.

Option Explicit
On Error Resume Next
Dim objIIS
Dim objSite
Dim varBindings
Dim intBindings
Dim blnChanged
Const strOldIP = ""
Const strNewIP = ""
Set objIIS = GetObject("IIS://LOCALHOST/W3SVC")
If (Err <> 0) Then
  WScript.Echo "Error " & Hex(Err.Number) & "(" & _
    Err.Description & ") occurred."
  For Each objSite In objIIS
    blnChanged = False
    If objSite.class = "IIsWebServer" Then
      varBindings = objSite.ServerBindings
      For intBindings = 0 To UBound(varBindings)
        If InStr(varBindings(intBindings),strOldIP) Then
          blnChanged = True
          varBindings(intBindings) = Replace(varBindings(intBindings),strOldIP,strNewIP)
        End If
    End If
    If blnChanged = True Then
      objSite.ServerBindings = varBindings      
    End If
End If
MsgBox "Finished!"

That’s all for now. Happy coding!

Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/

Converting NCSA log files to W3C format

One of the great utilities that ships with IIS is the CONVLOG.EXE application, which converts W3C or MS Internet Standard log files to NCSA format, where they can be processed by any of the applications that only parse NCSA log file information. The trouble is, what happens when you already have NCSA log files and you want W3C log files? You can't use the CONVLOG.EXE application, it only works in the opposite direction.

With that in mind, I wrote the following Windows Script Host (WSH) script that will read the current directory and convert all NCSA-formatted log files to W3C format. To use this code, just copy the code into notepad, and save it with a ".vbs" file extension on your system. To run it, copy the script to a folder that contains NCSA log files, (named "nc*.log"), then double-click it.

Option Explicit

Dim objIISLog
Dim objFSO
Dim objFolder
Dim objFile
Dim objOutputFile
Dim strInputPath
Dim strOutputPath
Dim strLogRecord

Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")

Set objFolder = objFSO.GetFolder(".")

For Each objFile In objFolder.Files

 strInputPath = LCase(objFile.Name)

 If Left(strInputPath,2) = "nc" And Right(strInputPath,4) = ".log" Then

  strOutputPath = objFolder.Path & "\" & "ex" & Mid(strInputPath,3)
  strInputPath = objFolder.Path & "\" & strInputPath

  Set objIISLog = CreateObject("MSWC.IISLog")
  objIISLog.OpenLogFile strInputPath, 1, "", 0, ""
  Set objOutputFile = objFSO.CreateTextFile(strOutputPath)


  objOutputFile.WriteLine "#Software: Microsoft Internet Information Services 5.0"
  objOutputFile.WriteLine "#Version: 1.0"
  objOutputFile.WriteLine "#Date: " & BuildDateTime(objIISLog.DateTime)
  objOutputFile.WriteLine "#Fields: date time c-ip cs-username s-ip s-port cs-method cs-uri-stem cs-uri-query sc-status cs(User-Agent)"

  Do While Not objIISLog.AtEndOfLog

   strLogRecord = BuildDateTime(objIISLog.DateTime)
   strLogRecord = strLogRecord & " " & FormatField(objIISLog.ClientIP)
   strLogRecord = strLogRecord & " " & FormatField(objIISLog.UserName)
   strLogRecord = strLogRecord & " " & FormatField(objIISLog.ServerIP)
   strLogRecord = strLogRecord & " " & FormatField(objIISLog.ServerPort)
   strLogRecord = strLogRecord & " " & FormatField(objIISLog.Method)
   strLogRecord = strLogRecord & " " & FormatField(objIISLog.URIStem)
   strLogRecord = strLogRecord & " " & FormatField(objIISLog.URIQuery)
   strLogRecord = strLogRecord & " " & FormatField(objIISLog.ProtocolStatus)
   strLogRecord = strLogRecord & " " & FormatField(objIISLog.UserAgent)
   objOutputFile.WriteLine strLogRecord



  objIISLog.CloseLogFiles 1
  objIISLog = Null
 End If


Function FormatField(tmpField)
 On Error Resume Next
 FormatField = "-"
 If Len(tmpField) > 0 Then FormatField = Trim(tmpField)
End Function

Function BuildDateTime(tmpDateTime)
 On Error Resume Next
 tmpDateTime = CDate(tmpDateTime)
 BuildDateTime = Year(tmpDateTime) & "-" & _
  Right("0" & Month(tmpDateTime),2) & "-" & _
  Right("0" & Day(tmpDateTime),2) & " " & _
  Right("0" & Hour(tmpDateTime),2) & ":" & _
  Right("0" & Minute(tmpDateTime),2) & ":" & _
  Right("0" & Second(tmpDateTime),2)
End Function

I hope this helps!