This article describes a simple WinForms utility that creates / destroys Microsoft(R) Internet Information Server(R) (IIS) Virtual Directories programmatically. The utility is then embedded in an Installer Project through Microsoft(R) Visual Studio .NET(R) 2003. I originally wrote this utility a few years ago when a client wanted an installer without buying an installer product AND did not want to always install to the default Web. In doing some research I became curious about not just creating and destroying virtual directories programmatically but also integrating these features with an installation project.
Create the Utility
Start by creating a VB.NET WinForms project called “VIT.WebSetup”. To this project, add a module “MainMod” and add two forms including “frmWebSetup.vb” and “frmWebTeardown.vb”. (Sorry about the names...some old habits die hard. I've since migrated away from that.) The utility is command-line driven and the “MainMod” module drives which form is shown based on the command-line parameters. The “Web Setup” form is the form used to specify the parameters for and create the virtual directory. It is linked to the installer during the “Commit“ portion of the installation process. View the Web Setup form screenshot. The “Web Teardown“ form is used to delete a virtual directory by name and is used during the “Uninstall“ portion of the installation process. View the Web Teardown form screenshot.
Add Some Code
Next, add some code. The code for the main module is responsible for parsing the command line and invoking the appropriate form. The code for each form is extremely straightforward. The “Web Setup” form contains two custom methods and three event handlers. The “Web Teardown” form contains one custom method and two event handlers.
“MainMod“ Methods
Main - This is the method by which the application starts. You must specify this method as the starting point for the application in the project properties. This method relies on the ProcessCommandLine method to parse the command line into a HashTable.
ProcessCommandLine - This method parses the command line into a HashTable object based on the presence or absence of the forward slash.
Here is the code for the main module.
Public Sub Main(ByVal args() As String)
Dim frmSetup As frmWebSetup
Dim frmTeardown As frmWebTeardown
Dim cmd As Hashtable
If args.Length > 0 Then
cmd = ProcessCommandLine(args)
If Not (cmd Is Nothing) Then
If cmd.Contains("u") Then ' Destroy or "unmake" a virtual directory.
frmTeardown =
New frmWebTeardown
Try
frmTeardown.txtVirtDirName.Text = cmd.Item("u").ToString()
Catch ex As System.NullReferenceException
' Do NO OP
' This occurs of the "/" isn't used to specify parms
' OR
' if a switch is empty.
Catch ex As Exception
' Do NO OP
End Try
frmTeardown.ShowDialog()
frmTeardown =
Nothing
Else ' Create a Virtual Directory
frmSetup =
New frmWebSetup
Try
frmSetup.txtVirtDirName.Text = cmd.Item("n").ToString()
frmSetup.txtVirtDirAlias.Text = cmd.Item("a").ToString()
frmSetup.txtVirtDirPath.Text = cmd.Item("d").ToString()
Catch ex As System.NullReferenceException
' Do NO OP
' This occurs if the "/" isn't used to specify parms
' OR
' if a switch is empty.
Catch ex As Exception
' Do NO OP
End Try
frmSetup.ShowDialog()
frmSetup =
Nothing
End If
End If
End If
cmd =
Nothing
End Sub
Private Function ProcessCommandLine(ByVal cmdargs() As String) As Hashtable
Dim ret As Hashtable
If cmdargs.Length Mod 2 = 0 Then
ret =
New Hashtable(CInt(cmdargs.Length / 2I))
For i As Integer = 0 To cmdargs.Length - 1 Step 2
ret.Add(cmdargs(i).ToString.ToLower.Replace("/", ""), cmdargs(i + 1).ToString())
Next
Else
ret =
New Hashtable(cmdargs.Length)
For i As Integer = 0 To cmdargs.Length - 1
ret.Add(i.ToString, cmdargs(i))
Next
End If
Return ret
End Function
“Web Setup“ Methods
CreateVirtualDirectory - This method, surprise surprise, is responsible for actually creating the virtual directory. It utilizes the Active Directory(R) Services Interface (ADSI) to perform its functions based on five parameters. The “VirtDirName“ String parameter specifies the name of the virtual directory to be created. The “VirtDirPath“ String paramter specifies the location of the virtual directory on the file system. The “ReadAccess“ and “ScriptAccess“ Boolean paramters are used to indicate the permissions for the virtual directory. Finally, the “VirtDirAlias“ String parameter specifies...you guessed it...the alias of the virtual directory.
IsValidInput - This method simply validates the input from the text fields on the form. It takes no parameters and actually simply checks that the text fields contain data. It performs no other validation.
btnBrowse_Click Event Handler - This handler invokes an “Open File Dialog“, allowing the user to select a directory which becomes the path to the virtual directory.
btnCreateVirtDir_Click Event Handler - This handler invokes the IsValidInput and CreateVirtualDirectory methods to actually create the virtual directory based on the input provided by the user.
btnCancel_Click Event Handler - Do I really need to explain this one?
Here is the code for this form:
Private Sub CreateVirtualDirectory(ByVal VirtDirName As String, ByVal VirtDirPath As String, ByVal ReadAccess As Boolean, ByVal ScriptAccess As Boolean, ByVal VirtDirAlias As String)
Dim IIsWebVDirRootObj As Object
Dim IIsWebVDirObj As Object
' Create an instance of the virtual directory object
' that represents the default Web site.
IIsWebVDirRootObj = GetObject("IIS://localhost/W3SVC/1/Root")
' Use the Windows ADSI container object "Create" method to create
' a new virtual directory.
IIsWebVDirObj = IIsWebVDirRootObj.Create("IIsWebVirtualDir", VirtDirName)
' Use the Windows ADSI object "Put" method to
' set some required properties.
IIsWebVDirObj.Put("Path", VirtDirPath)
IIsWebVDirObj.Put("AccessRead", ReadAccess)
IIsWebVDirObj.Put("AccessScript", ScriptAccess)
' Use the AppCreate2 method of the IIS ADSI provider to
' create an application on the new virtual directory.
IIsWebVDirObj.AppCreate2(1)
IIsWebVDirObj.Put("AppFriendlyName", VirtDirAlias)
' Use the Windows ADSI object "SetInfo" method to
' save the data to the metabase.
IIsWebVDirObj.SetInfo()
End Sub
Private Function IsValidInput() As Boolean
Dim result As Boolean = True
result = result
And (Me.txtVirtDirName.Text.Trim.Length > 0)
result = result
And (Me.txtVirtDirPath.Text.Trim.Length > 0)
result = result
And (Me.txtVirtDirAlias.Text.Trim.Length > 0)
Return result
End Function
Private Sub btnBrowse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBrowse.Click
If Me.ofdBrowse.ShowDialog() = DialogResult.Cancel Then
Else
Me.txtVirtDirPath.Text = ofdBrowse.SelectedPath
End If
End Sub
Private Sub btnCreateVirtDir_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCreateVirtDir.Click
If Me.IsValidInput() Then
Try
Me.CreateVirtualDirectory(Me.txtVirtDirName.Text, Me.txtVirtDirPath.Text, Me.chkAccessRead.Checked, Me.chkAccessScript.Checked, Me.txtVirtDirAlias.Text)
MessageBox.Show("The virtual directory was successfully created.")
Catch ex As System.Runtime.InteropServices.COMException
MessageBox.Show("The following COM exception occurred: " & ex.Message)
Catch ex As Exception
MessageBox.Show("The following exception occurred: " & ex.Message)
End Try
Else
MessageBox.Show("Required Fields are Missing")
End If
End Sub
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
If DialogResult.Yes = MessageBox.Show("Are you sure you want to stop creating virtual directories?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) Then
Application.Exit()
End If
End Sub
“Web Teardown“ Methods
btnDestroyVirtDir_Click Event Handler - You betcha! This uses basically the same technique as the CreateVirtualDirectory method of the “Web Setup” form. Instead of creating, of course, it destroys the virtual directory specified by the user.
The “Web Teardown” form also contains IsValidInput and btnCancel_Click Event Handler methods, like the “Web Setup” form. Here is the code for this form.
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
If DialogResult.Yes = MessageBox.Show("Are you sure you want to stop destroying virtual directories?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) Then
Application.Exit()
End If
End Sub
Private Sub btnDestroyVirtDir_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDestroyVirtDir.Click
Dim IIsWebVDirObj As Object
Dim IIsWebDirRoot As Object
If Me.IsValidInput Then
Try
IIsWebVDirObj = GetObject("IIS://localhost/W3SVC/1/ROOT/" &
Me.txtVirtDirName.Text)
IIsWebVDirObj.AppDeleteRecursive()
IIsWebVDirObj.SetInfo()
IIsWebVDirObj =
Nothing
IIsWebDirRoot = GetObject("IIS://localhost/W3SVC/1/ROOT")
IIsWebDirRoot.Delete("IIsWebVirtualDir",
Me.txtVirtDirName.Text)
IIsWebDirRoot =
Nothing
MessageBox.Show("The virtual directory was successfully destroyed.")
Catch ex As System.Runtime.InteropServices.COMException
MessageBox.Show("The following COM exception occurred: " & ex.Message)
Catch ex As Exception
MessageBox.Show("The following exception occurred: " & ex.Message)
End Try
Else
MessageBox.Show("Required Fields are Missing")
End If
End Sub
Private Function IsValidInput() As Boolean
Dim result As Boolean = True
result = result
And (Me.txtVirtDirName.Text.Trim.Length > 0)
Return result
End Function
Integrating with a Setup Project
Now that the Web Setup utility is built, it can be used from a setup project. There are basically two areas of customization in the setup project for integrating the utility. Firstly, the “File System Editor” is used to include the utility. Secondly, the “Custom Actions Editor” is used to invoke the utility.
File System Editor Configuration
The utility must be included with the distribution to be invoked. There are two ways to do this and they both follow the same basic steps. You can include the “Primary Output” from the “WebSetup” project. Alternately, you can include the stand-alone executable resulting from building the “Web Setup” project.
Including the “Primary Output”
- Open the “File System Editor“
- Right-Click “Application Folder -> Add -> Project Output...“
- Choose the “WebSetup“ project from the “Project“ pick list and select “Primary Output“.
- Click “OK“.
Including the Executable
- Open the “File System Editor“
- Right-Click “Application Folder -> Add -> File...“
- Locate the .exe file and click “Open“.
Custom Actions Editor Configuration
Once the “WebSetup” file is included, modify the custom actions to invoke the utility. Remember that the utility supports both creation and destruction of virtual directories so custom actions should be created for each. Follow these steps to properly configure the custom actions. Note that you do not want to create a virtual directory until the install is successful, so you will use the “Commit“ area for the creation custom action.
Configuring to Create Virtual Directories
- Open the “Custom Actions Editor“.
- Right-Click on “Commit“ and choose “Add Custom Action...“
- Double-Click “Application Folder“ and choose either the “Primary Output...“ or executable file name, depending on which you chose to include.
- Right-Click on the newly created custom action and select “Rename“.
- Rename the custom action to “Create Virtual Directory“.
- While the custom action is selected, view its properties.
- Change the “Arguments“ property to read:
/d [TARGETDIR] /a alias /n name
- Substitute your alias for “alias“ and your virtual directory name for “name“. Leave the target directory as shown to pull the target directory from the selected installation folder.
Configuring to Delete Virtual Directories
- Open the “Custom Actions Editor“.
- Right-Click on “Uninstall“ and choose “Add Custom Action...“
- Double-Click “Application Folder“ and choose either the “Primary Output...“ or executable file name, depending on which you chose to include.
- Right-Click on the newly created custom action and select “Rename“.
- Rename the custom action to “Destory Virtual Directory“.
- While the custom action is selected, view its properties.
- Change the “Arguments“ property to read:
/u name
- Substitute your virtual directory name for “name“.
Next Steps
There are some things that can be done to improve this utility.
- Some better validation can occur.
- Consider reading virtual directories from ADSI, providing some user guidance.
- Review this URL for the same basic approach with some other ADSI parameters included: http://www.vbforums.com/showthread.php?t=347207http://www.vbforums.com/showthread.php?t=347207