Update 30th July 2009: After deploying this to a development server there were a few tweaks I needed to make to get it working. IÂ have amended the post as necessary.
I needed to be able to create a virtual directory in IIS via my ASP.NET application. I found this nice little example in VB.NET and converted it to C#. You need to add a reference to System.DirectoryServices to use it. The VB.NET example always puts the new virtual directory in the default website, so I have amended it to allow choosing the server and website you want to place the virtual directory under.
private void CreateVirtualDir(string serverName, string website, string appName, string path)
{
   DirectoryEntry IISSchema = new DirectoryEntry(string.Concat("IIS://", serverName, "/Schema/AppIsolated"));
   bool canCreate = IISSchema.Properties["Syntax"].Value.ToString().ToUpper() != "BOOLEAN";
   IISSchema.Dispose();
   //get the identifier for the site we want
   int identifier = 0;
   DirectoryEntry root = new DirectoryEntry(string.Concat("IIS://", serverName, "/W3SVC"));
   foreach(DirectoryEntry de in root.Children)
   {
       if (de.SchemaClassName.ToUpper().Equals("IISWEBSERVER") &&
           de.Invoke("Get", "ServerComment").ToString().ToUpper().Equals(website.ToUpper()))
       {
           identifier = Convert.ToInt32(de.Name);
           break;
       }
   }
   if (canCreate && identifier > 0)
   {
       bool pathCreated = false;
       try
       {
           DirectoryEntry iisAdmin = new DirectoryEntry(string.Format("IIS://{0}/W3SVC/{1}/Root", serverName, identifier));
           //make sure folder exists
           if (!System.IO.Directory.Exists(path))
           {
               System.IO.Directory.CreateDirectory(path);
               pathCreated = true;
           }
           //If the virtual directory already exists then delete it
           foreach (DirectoryEntry vd in iisAdmin.Children)
           {
               if (vd.Name.Equals(appName))
               {
                   iisAdmin.Invoke("Delete", new string[] { vd.SchemaClassName, appName });
                   iisAdmin.CommitChanges();
                   break;
               }
           }
           //Create and setup new virtual directory
           DirectoryEntry vDir = iisAdmin.Children.Add(appName, "IIsWebVirtualDir");
           vDir.Properties["Path"][0] = path;
           vDir.Properties["AppFriendlyName"][0] = appName;
           vDir.Properties["EnableDirBrowsing"][0] = false;
           vDir.Properties["AccessRead"][0] = true;
           vDir.Properties["AccessExecute"][0] = true;
           vDir.Properties["AccessWrite"][0] = false;
           vDir.Properties["AccessScript"][0] = true;
           vDir.Properties["AuthNTLM"][0] = true;
           vDir.Properties["EnableDefaultDoc"][0] = true;
           vDir.Properties["DefaultDoc"][0] = "default.htm,default.aspx,default.asp";
           vDir.Properties["AspEnableParentPaths"][0] = true;
           vDir.CommitChanges();
           //the following are acceptable params
           //INPROC = 0
           //OUTPROC = 1
           //POOLED = 2
           vDir.Invoke("AppCreate", 1);
       }
       catch (Exception ex)
       {
           if (pathCreated)
           {
               System.IO.Directory.Delete(path);
           }
           throw ex;
       }
   }
   else
   {
       throw new ApplicationException("Failed to create Virtual Directory");
   }
}
To create a new virtual directory I can then call the method like this:
try
{
   CreateVirtualDir("localhost", "MyWebSite" "MyVirtualDirectory", @"c:\sites\mysite");
}
catch (Exception ex)
{
   lblMessage.Text = string.Concat("An error occurred: ", ex.Message);
}
When I deployed this to a development server I got an ‘Access is denied’ error on this following line:
vDir.CommitChanges();
This is because IIS administration need to be done by a user in the administrator group which is the ASPNET user is not. To resolve this I created a new window user on the server which was a member of the administrator group. I then added the following to my Web.config:
<system.web> Â Â Â <identity impersonate="true" userName="username" password="password" /> </system.web>
You could also wrap this in an pages element to restrict which pages will impersonate this identity.


