Wednesday, December 30, 2009

Getting list of web sites from IIS metabase

Here we are going to see how we can get the list of web sites available using IIS metabase.
We will start with defining the types we are going to use. Class WebSite is used to hold information about a web site and enum ServerState specifies its state. The states are self explanatory.

public class WebSite
{
   private int _Id;
   public int Id
   {
      get { return _Id; }
      set { _Id = value; }
   }

   private string _Name;
   public string Name
   {
      get { return _Name; }
      set { _Name = value; }
   }

   private string _Description;
   public string Description
   {
      get { return _Description; }
      set { _Description = value; }
   }

   private string _ApplicationPool;
   public string ApplicationPool
   {
      get { return _ApplicationPool; }
      set { _ApplicationPool = value; }
   }

   private string _FolderPath;
   public string FolderPath
   {
      get { return _FolderPath; }
      set { _FolderPath = value; }
   }

   private ServerState _ServerState;
   public ServerState ServerState
   {
      get { return _ServerState; }
      set { _ServerState = value; }
   }
}

public enum ServerState
{
   Unknown = 0,
   Starting = 1,
   Started = 2,
   Stopping = 3,
   Stopped = 4,
   Pausing = 5,
   Paused = 6,
   Continuing = 7
}

We can use System.DirectoryServices.DirectoryEntry for accessing IIS metabase. For getting the registered web sites, we need to iterate through the child nodes of "IIS://localhost/W3SVC". A childer is identified as a web site if the SchemaClassName property is IIsWebServer. IIS assigns unique integer number to each websites which typically starts from 1. The Name property provides this value.

public List<WebSite> GetWebSites()
{
   string metabasePath = "IIS://localhost/W3SVC";
   DirectoryEntry root = null;
   List<WebSite> webSites = new List<WebSite>();
   try
   {
      root = new DirectoryEntry(metabasePath);
      bool hasAppPools = HasApplicationPools();
      foreach (DirectoryEntry s in root.Children)
      {
         int siteId;
         if (s.SchemaClassName == "IIsWebServer" && Int32.TryParse(s.Name, out siteId))
         {
            WebSite webSite = new WebSite();
            webSite.Id = siteId;
            webSite.Name = s.Properties["ServerComment"].Value.ToString();
            webSite.Description = s.Properties["ServerComment"].Value.ToString();
            webSite.FolderPath = GetFolderPath(s);
            webSite.ServerState = GetServerState(s.Properties["ServerState"].Value.ToString());
            if (hasAppPools)
            {
               webSite.ApplicationPool = s.Properties["AppPoolId"].Value.ToString();
            }
            webSites.Add(webSite);
         }
      }
   }
   catch { }
   finally
   {
      if (root != null)
         root.Close();
   }
   return webSites;
}

public bool IsValidMetabasePath(DirectoryEntry entry)
{
   try
   {
      if (entry != null && !string.IsNullOrEmpty(entry.SchemaClassName))
         return true;
   }
   catch { }
   return false;
}

public bool HasApplicationPools()
{
   string metabaseAppPoolsPath = "IIS://localhost/W3SVC/AppPools";
   DirectoryEntry appPoolsEntry = new DirectoryEntry(metabaseAppPoolsPath);
   return IsValidMetabasePath(appPoolsEntry);
}

For getting the website root path, we need to read the Path property of its child named ROOT.

private string GetFolderPath(DirectoryEntry server)
{
   foreach (DirectoryEntry s in server.Children)
      if (s.Name.ToUpper() == "ROOT")
         return s.Properties["Path"].Value.ToString();
   return "";
}

private ServerState GetServerState(string serverStatePropertyValue)
{
   switch (serverStatePropertyValue)
   {
      case "1": return ServerState.Starting;
      case "2": return ServerState.Started;
      case "3": return ServerState.Stopping;
      case "4": return ServerState.Stopped;
      case "5": return ServerState.Pausing;
      case "6": return ServerState.Paused;
      case "7": return ServerState.Continuing;
   }
   return ServerState.Unknown;
}

No comments:

Post a Comment