4

I am trying to create a list of all virtual directories within an IIS site. However, I have found that trying to do this varies dramatically in the older versions of IIS. In IIS 7 this is a relatively easy task via C# but I can't seem to find a good method for doing this in IIS 6 and 5.

I have tried using the System.DirectoryServices.DirectoryEntry but that doesn't seem to give me the desired output.

I am the server administrator so I'm open to using other things such as .vbs files that are built into IIS as well as writing my own code.

Avitus
  • 15,640
  • 6
  • 43
  • 53

4 Answers4

4

Here are two examples that should work across IIS 5, 6 and 7 (with IIS 6 WMI compatibility installed). I successfully tested both with IIS 5 and 7.

VBScript version

Function ListVirtualDirectories(serverName, siteId) 
    Dim webSite 
    Dim webDirectory

    On Error Resume Next 

    Set webSite = GetObject( "IIS://" & serverName & "/W3SVC/" & siteId & "/ROOT" ) 
    If ( Err <> 0 ) Then 
        Err = 0 
        Exit Function 
    Else 
        For Each webDirectory in webSite
            If webDirectory.Class = "IIsWebVirtualDir" Then 
                WScript.Echo "Found virtual directory " & webDirectory.Name
            End If 
        Next
    End If   
End Function

C# version

void ListVirtualDirectories(string serverName, int siteId)
{            
       DirectoryEntry webService = new DirectoryEntry("IIS://" + serverName + "/W3SVC/" + siteId + "/ROOT");

       foreach (DirectoryEntry webDir in webService.Children)
       {
           if (webDir.SchemaClassName.Equals("IIsWebVirtualDir"))
               Console.WriteLine("Found virtual directory {0}", webDir.Name);
       }
}
Garett
  • 16,632
  • 5
  • 55
  • 63
  • This is very helpful. However it seems to only get the Virtual Directories in the site's root folder, to get all Virtual Directories for the site I will have to do this recursively by going into the children's children and so on, correct? – Despertar May 09 '12 at 21:25
  • @Despertar Yes, you would have to write a recursive method that iterates each child's children. It should be pretty straightforward to do. I'll update my answer to do this when I have sometime. – Garett May 09 '12 at 23:22
  • 1
    I provided the helper methods to do this below. I know time is not always easy to find. – Despertar May 09 '12 at 23:34
2

Here are two helper functions to add onto Garetts answer. With these, you can loop through each domain and get all its virtual directories, including ones that are not in the domains root folder.

Get Site ID from domain name:

    string GetSiteID(string domain)
    {
        string siteId = string.Empty;

        DirectoryEntry iis = new DirectoryEntry("IIS://localhost/W3SVC");
        foreach (DirectoryEntry entry in iis.Children)
            if (entry.SchemaClassName.ToLower() == "iiswebserver")
                if (entry.Properties["ServerComment"].Value.ToString().ToLower() == domain.ToLower())
                    siteId = entry.Name;

        if (string.IsNullOrEmpty(siteId))
            throw new Exception("Could not find site '" + domain + "'");

        return siteId;
    }

Get all descendant entries (recursively) for site entry

    static DirectoryEntry[] GetAllChildren(DirectoryEntry entry)
    {
        List<DirectoryEntry> children = new List<DirectoryEntry>();
        foreach (DirectoryEntry child in entry.Children)
        {
            children.Add(child);
            children.AddRange(GetAllChildren(child));
        }

        return children.ToArray();
    }

Mapping Site ID's for large number of sites

Edit: After testing this with a server containing several hundred domains, GetSiteID() performs very slow because it is enumerating all the sites again and again to get the id. The below function enumerates the sites only a single time and maps each one to its id and stores it in a dictionary. Then when you need the site id you pull it from the dictionary instead, Sites["domain"]. If you are looking up virtual directories for all sites on a server, or a large amount, the below will be much faster than GetSiteID() above.

    public static Dictionary<string, string> MapSiteIDs()
    {  
        DirectoryEntry IIS = new DirectoryEntry("IIS://localhost/W3SVC");
        Dictionary<string, string> dictionary = new Dictionary<string, string>(); // key=domain, value=siteId
        foreach (DirectoryEntry entry in IIS.Children)
        {
            if (entry.SchemaClassName.ToLower() == "iiswebserver")
            {
                string domainName = entry.Properties["ServerComment"].Value.ToString().ToLower();
                string siteID = entry.Name;
                dictionary.Add(domainName, siteID);
            }
        }

        return dictionary;
    }
Despertar
  • 21,627
  • 11
  • 81
  • 79
0

have you tried using GetObject("IIS://ServerName/W3SVC")

You do it in VBS like this

'Get the IIS Server Object
Set oW3SVC = GetObject("IIS://ServerName/W3SVC/1/ROOT")

For Each oVirtualDirectory In oW3SVC

    Set oFile = CreateObject("Scripting.FileSystemObject")
    Set oTextFile = oFile.OpenTextFile("C:\Results.txt", 8, True)

    oTextFile.WriteLine(oVirtualDirectory.class + " -" + oVirtualDirectory.Name)
    oTextFile.Close

Next
Set oTextFile = Nothing
Set oFile = Nothing

Wscript.Echo "Done"

I have an article about it here -> http://anyrest.wordpress.com/2010/02/10/how-to-list-all-websites-in-iis/

Raymund
  • 7,684
  • 5
  • 45
  • 78
  • This lists the websites under IIS. I'm trying to get all the virtual directories under 1 site. – Avitus Oct 15 '10 at 02:02
  • I edited my answer so that it lists the directories and what type of directory it is. Hope this works – Raymund Oct 15 '10 at 02:04
0

I know you're asking for VB solutions, I don't really know VB, I'm more of a C# person. Anyway, here is a little bit of C#.NET code taken from an app I wrote some time ago which lists the IIS virtual directories...

    using System.DirectoryServices;

    private DirectoryEntry _iisServer = null;
    private DirectoryEntry iisServer
    {
        get
        {
            if (_iisServer == null)
            {
                string path = string.Format("IIS://{0}/W3SVC/1", serverName);
                _iisServer = new DirectoryEntry(path);
            }
            return _iisServer;
        }
    }

    private IDictionary<string, DirectoryEntry> _virtualDirectories = null;
    private IDictionary<string, DirectoryEntry> virtualDirectories
    {
        get
        {
            if (_virtualDirectories == null)
            {
                _virtualDirectories = new Dictionary<string, DirectoryEntry>();

                DirectoryEntry folderRoot = iisServer.Children.Find("Root", VirDirSchemaName);
                foreach (DirectoryEntry virtualDirectory in folderRoot.Children)
                {
                    _virtualDirectories.Add(virtualDirectory.Name, virtualDirectory);
                }
            }
            return _virtualDirectories;
        }
    }

Hopefully you will be able to get the general idea from that.

Allen Rice
  • 19,068
  • 14
  • 83
  • 115
Antony Scott
  • 21,690
  • 12
  • 62
  • 94