Create a virtual directory in IIS using ASP.NET and C#

0

Posted by Joe | Posted in ASP.NET, C# | Posted on 28-07-2009

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.

Post to Twitter Post to Delicious Post to Digg Post to Facebook Post to Reddit

Write a comment