Build a .NET Windows XP "Site Changer" Utility

by Peter A. Bromberg, Ph.D.

Peter Bromberg
Be slow in choosing a friend, slower in changing. -- Benjamin Franklin

I do most of my ASP.NET development on Windows Server 2003, mostly because I want to use the full IIS 6.0 in Http.sys mode and enjoy the fact that I can bind multiple IP Addresses to multiple "real" web sites in IIS. There are always minor inconsistencies between Windows Server and Windows XP, most notably that if a web site you are developing is intended to be deployed at the root of a Webserver IP Address (not as a virtual directory, which is how you must develop on Windows XP, where IIS does not support multiple web sites), you can get links messed up -- and so I get the benefit of not having to worry about different behavior of master page references, relative links and so forth.



There are several utilities and hacks that allow you to create and switch to multiple web sites on Windows XP, but since you can only have one running at the same time, they don't accomplish much. (By the way, this is known as the "upgrade close" in sales jargon - you give the customer the low-priced model that is stunted in some way in the hopes they'll "upgrade" to the more expensive model that has all features enabled.) Also, I have found that these utilities can cause a whole bunch of new headaches such as VS.NET making virtual directories that go into the wrong places and similar unhappy little side effects. I have a notebook on which I run Windows XP Pro x64, so I still needed to have some sort of site-switching utility for that machine.

The fact is that the most reliable way to be able to work on multiple "root" web sites in Windows XP is to leave the one default site in IIS, and just switch the location of it's home directory to the folder for the web site that you want to work on. That is inconvenient with IIS Manager, so I put together this little "site switcher" utility so I could drag it's shortcut to the QuickLaunch area on the TaskBar and bring it up quickly to be able to select one of my folders and reset IIS to have that site location as its home directory. The additional benefit is that we aren't disturbing the default "bad boy" behavior that Microsoft intended for Windows XP users (forget about the 10 connection limit, that's another issue, but there are ways to "upgrade" that too.) -- and so we don't have any of the bad side effects of the other utilities.

While I was at it, I added another simple utility, the ability to kill the ASPNET worker process and force it to recycle. While you can do IISReset and bring "everything" down and then back up, most of the time if you are testing or working on code that you need to release from memory for debugging, it's better to just get ASPNET to go away and recycle, and leave IIS alone.

The UI of my utility is very compact and easy to understand:

And now, some code:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.DirectoryServices;

using System.Configuration;

using System.Diagnostics;

 

namespace SiteChanger

{

 

    public partial class Form1 : Form

    {

        string workerProcessName = ConfigurationManager.AppSettings["workerProcessName"];

 

        public Form1()

        {

            InitializeComponent();

        }

 

        private void button1_Click(object sender, EventArgs e)

        {

            try

            {

                string path = this.comboBox1.Text;

                if (path == null || path.Length == 0)

                {

                    label1.Text = "Please enter text or make a selection.";

                    return;

                }

                DirectoryEntry root = new DirectoryEntry                             ("IIS://localhost/W3SVC/1/Root");

                root.Properties["Path"].Clear();

                root.Properties["Path"].Insert(0, path);

                root.CommitChanges();

                label1.Text = "root changed to " + path;

            }

            catch (Exception ex)

            {

                this.label1.Text = ex.Message;

            }

        }

 

        private void Form1_Load(object sender, EventArgs e)

        {

            string stuff =

                System.Configuration.ConfigurationManager.AppSettings["vDirs"];

            string[] items = stuff.Split(';');

            this.comboBox1.Items.AddRange(items);

        }

 

        private void button2_Click(object sender, EventArgs e)

        {

            DialogResult res =

                MessageBox.Show("Kill ASP.NET Process?", "Kill Process",

                                                MessageBoxButtons.OKCancel);

            if (res == DialogResult.OK)

            {

                try

                {

                    Process[] procs = Process.GetProcessesByName(workerProcessName);

                    procs[0].Kill();

                    this.label1.Text = "Process Killed.";

                }

                catch (Exception ex)

                {

                    this.label1.Text = ex.Message;

                }

            }

        }

    }

}

You can see that when our Form loads we grab the value in the "vDirs" appSettings element as seen below, and split this into a string array on the semicolon delimiter. Then we just add this array to our combobox via the AddRange method. When you select a folder location in the Combo and press the button, we use a DirectoryServices Directory entry to switch the Path property of our Site number 1 Root, and then we commit the change.

Similarly, if you want to kill the ASPNET Worker process, this button finds it via GetProcessesByName and calls the Kill method on that process. I am storing the vDir folders in the configuration file for obvious reasons; you want an easy way to edit your list of folder locations if you start working on a new web site. But, we also store the NAME of the ASPNET Worker process there too since it can be different on different versions of the OS (64-bit vs 32-bit, etc.).

The app.config file:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <appSettings>

    <add key="vDirs" value="C:\Inetpub\wwwroot;C:\wwwroot\yoursite.com;C:\Temp"/>

    <add key="workerProcessName" value="aspnet_wp"/>

  </appSettings>

</configuration>

I hope this little exercise is useful to you; I certainly find it handy!

Download the Visual Studio 2005 solution that acommpanies this article


Peter Bromberg is a C# MVP, MCP, and .NET consultant who has worked in the banking and financial industry for 20 years. He has architected and developed web - based corporate distributed application solutions since 1995, and focuses exclusively on the .NET Platform.
Article Discussion: