Obtaining IIS logs for specific sites programmatically

Posted on Saturday, April 4, 2009

The company I work for switched to a different system for web analytics which did not support drawing web log data from multiple servers therefore it became necessary to copy IIS web logs to a central location with the site name as the folder name. Since a site's log directory name is composed of "W3SVC" + site id, if we can obtain the site id we can link a specific site to its log folder. After a little research I found that this could be done using System.DirectoryServices which, among other things, gives access to IIS's metadata thus providing the link between site name and site id. The following code iterates through the sites in IIS and copies their logs to a folder named with the host header in some destination directory:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Configuration;
using System.DirectoryServices;
namespace DirectoryServicesExample
 class Program
  static String logPath = @"WINDOWS\system32\LogFiles";
  static void Main(string[] args)
   //Get the metadata for the instance of IIS running on the current computer
   DirectoryEntry iis = new DirectoryEntry("IIS://localhost/w3svc");
   //Iterate through the children of the IIS directory entry
   foreach(DirectoryEntry site in iis.Children)
    //Check to make sure that the child is a site. IIS websites have a schema class name of IISWebServer
    if(site.SchemaClassName == "IIsWebServer")
     //Retrieve the comment property of the site
     String comment = (String)site.Properties["ServerComment"].Value;
     //Creates the path to the current site's log file directory. site.Name is the site's id
     String sourcePath = Path.Combine(Path.Combine(@"C:\", logPath), "W3SVC" + site.Name);
     String hostHeader = null;

     /*Retrieves the site's host header/port bindings. If there is more than one binding, then
      * site.Properties["ServerBindings"].Value returns an object array of binding strings
      * (:80:host.header.com)*/
     String serverBinding = (site.Properties["ServerBindings"].Value as String);
      String[] bindingParts = serverBinding.Split(':');
      if(bindingParts.Length == 3)
       hostHeader = bindingParts[2].Replace('.', '_');
      String destinationPath = Path.Combine(ConfigurationSettings.AppSettings["DestinationDirectoryPath"], hostHeader);
      FileInfo[] logFiles = new DirectoryInfo(sourcePath).GetFiles();
      foreach(FileInfo logFile in logFiles)
       logFile.CopyTo(Path.Combine(destinationPath, logFile.Name));