Introduction
There
are situations, in web applications, when is need to create a virtual
directory. For example, we have an application that generates automatically
websites for users, creating files on disk, such as pages, images etc, and we
want to create a virtual directory for every website we created on disk; It’s
annoying to create manually a virtual directory for every physical directory
created on disk; instead, we can create a functionality which allows us to
create these virtual directories programmatically.
How to do that?
Let’s
implement this functionality in following example. We create a website
application based on framework 2.0, called VirtualDirectory, and add to
solution a project of type ClassLibrary, called Utils.
Add
class VirtualDirectory, and reference System.DirectoryServices to Utils
project. This library comes with classes used to implement this functionality.
This
mechanism will function as follow: user can provide virtual directory name in
interface, and application will gel the rest of the settings:
- name
of IIS server which will host the application
- source
folder – the folder of the application, which will be created (in our case,
this application)
- destination
folder – the folder where will be copies the new application. Note that on this
directory must have writing rights the user NerworkService or the user under
our application is running.
will
be loaded from a xml file, and the application will be created.
Let’s take a look to the listing of
VirtualFolder class code:
using System;
using
System.Collections.Generic;
using
System.Collections;
using
System.Text;
using System.IO;
using System.Xml;
using
System.Data;
using
System.Data.SqlClient;
using
System.DirectoryServices;
using
System.Configuration;
namespace Utils
{
public class
VirtualDirectory
{
public VirtualDirectory()
{
}
/// Load XML file with archive
settings
private static
XmlDocument LoadXMLSettings()
{
XmlDocument xmlSettings = new XmlDocument();
string xmlSettingsPath = ConfigurationManager.AppSettings["ArchiveSettingsPath"];
try
{
xmlSettings.Load(xmlSettingsPath + "DirSettings.xml");
}
catch
{
throw new
ApplicationException("Settings file could not be opened");
}
return xmlSettings;
}
}
/// Copy a directory to specified
destination
private static
void CopyDir(string
sourceDir, string destDir)
{
DirectoryInfo dir = new DirectoryInfo(sourceDir);
try
{
if (!Directory.Exists(destDir))
Directory.CreateDirectory(destDir);
}
catch
{
throw new
Exception("Cannot
create directory at location " + destDir);
}
FileInfo[] files = dir.GetFiles("*");
foreach (FileInfo
filePath in files)
{
try
{
filePath.CopyTo(Path.Combine(destDir,
filePath.Name));
}
catch
{
throw new
Exception(
"Cannot create file " +
filePath.Name + " at location " +
destDir);
}
}
DirectoryInfo[] children =
dir.GetDirectories();
foreach (DirectoryInfo
dirChild in children)
{
CopyDir(Path.Combine(sourceDir,
dirChild.Name), Path.Combine(destDir,
dirChild.Name));
}
}
/// Copy application directory to
specified destination
private static
void CopyDirectory(XmlDocument
xmlSettings, string AppName)
{
string sourceDir =
GetXmlSetting(xmlSettings, "WebAppSourceFolder");
string destDir =
GetXmlSetting(xmlSettings, "WebAppDestinationFolder");
destDir += AppName;
if (!Directory.Exists(destDir))
Directory.CreateDirectory(destDir);
else
{
throw new Exception("Directory
" + destDir + " already
exists!");
}
try
{
CopyDir(sourceDir,
destDir);
}
catch {
throw new Exception("Cannot
copy directory at location " + destDir);
}
}
/// Creates virtual directory for
application
public static
string CreateApplication(string AppName)
{
try
{
XmlDocument xmlSettings = LoadXMLSettings();
CopyDirectory(xmlSettings, AppName);
CreateVirtualDirectory(AppName, xmlSettings);
}
catch(Exception
ex) {
return ex.Message;
}
return "Directory
created";
}
/// Creates a virtual directory in IIS
private static
void CreateVirtualDirectory(string appName, XmlDocument
xmlSettings)
{
string IISSServerName =
GetXmlSetting(xmlSettings, "WebDestinationServer");
string applicationPath =
GetXmlSetting(xmlSettings, "WebAppDestinationFolder");
try
{
DirectoryEntry teamTrackDirSchema = new System.DirectoryServices.DirectoryEntry(
"IIS://" +
IISSServerName + "/Schema/AppIsolated");
bool canCreate =
!(teamTrackDirSchema.Properties["Syntax"].
Value.ToString() == "BOOLEAN");
teamTrackDirSchema.Dispose();
if (canCreate)
{
System.DirectoryServices.DirectoryEntry
virtualParent =
new System.DirectoryServices.DirectoryEntry("IIS://"
+
IISSServerName + "/W3SVC/1/Root");
//if virtual dir exists, delete it
foreach (System.DirectoryServices.DirectoryEntry vd in
virtualParent.Children)
{
if (vd.Name == appName)
{
virtualParent.Invoke("Delete",
new String[]
{
vd.SchemaClassName, appName });
virtualParent.CommitChanges();
}
}
//create virtual directory
System.DirectoryServices.DirectoryEntry
vDir =
virtualParent.Children.Add(appName, "IIsWebVirtualDir");
vDir.Properties["Path"][0]
= applicationPath + appName;
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]
= false;
//Anonymous access = false | Integrated win auth
= true
vDir.Properties["AuthFlags"].Value
= 4;
vDir.Properties["EnableDefaultDoc"][0]
= true;
vDir.Properties["DefaultDoc"][0]
= "default.htm,default.aspx,default.asp";
vDir.Properties["AspEnableParentPaths"][0]
= true;
vDir.CommitChanges();
vDir.Invoke("AppCreate",
1);
}
else
throw new
ApplicationException("Cannot create virtual directory " + appName);
}
catch(Exception
ex)
{
throw new
ApplicationException("Error creating virtual directory " + appName);
}
}
/// read a key from archive
configuration file
private static
string GetXmlSetting(XmlDocument
xmlSettings, string Key)
{
try
{
return xmlSettings.DocumentElement.SelectSingleNode(
"archiveSetting[@key='" + Key + "']").Attributes["value"].Value;
}
catch {
throw new
ApplicationException(
"Setarea " + Key + " nu exista in fisierul de setari arhivare");
}
}
}
The
main function called here is CreateApplication, which receive application name
as parameter from interface, and does the following operations:
- load
settings from a xml file
- copy
new application to a location specified in the settings file
- create
virtual directory
Virtual
directory is created using class DirectoryEntry, from library
System.DirectoryEntry:
new System.DirectoryServices.DirectoryEntry("IIS://"
+ IISSServerName + "/W3SVC/1/Root"
In
this example, we create a virtual directory under the first website ("/W3SVC/1/Root")
found under IIS WebSites (in many cases, Default Web Site). Probably it’s
better to provide the name of website under IIS websites which we want to be
parent for our virtual directory, search it in websites list, return its index
and use it to init the virtual directory object. Here, it’s enough to create
under the first website in websites list (is Default Web Site in our case).
In
interface, we have a textbox where we introduce name of virtual directory, and
a button Create, to create the directory. This button has associated the code:
string
VirtualDir = txtVirtDirName.Text;
if (VirtualDir != "")
{
string Status = Utils.VirtualDirectory.CreateApplication(VirtualDir);
lblStatus.Text =
Status;
}
If
an error occurs to this operation, it will be displayed, else, will be
displayed text “Directory created”
VirtualDirectory.rar (25.68 kb)