November 13, 2009 4 Comments
Last time I discussed the the unfortunate crippling of the Visual Studio built-in web server, webdev.webserver, so that it can only process requests that originate from localhost and the side-effect that this creates a big impedance barrier to testing multiple versions of Internet Explorer with your web apps. I promised a solution to the dilemma.
The key is to run your different versions of IE in virtualization software and use a personal proxy server to forward their requests. If the proxy is running on your host OS and the browsers in the client VMs use the host OS proxy then, from the perspective of webdev.webserver in your host OS, all of the requests will appear to originate from localhost and it will serve them.
There are a few gotchas.
Step 1: loopback adapter
The loopback adapter is a virtual network interface device. It provides a way for us to create a shared network between the virtual machines and the host machines without altering the configuration of any real network interfaces.
Install the loopback adapter via Device Manager (devmgmt.msc) by right-clicking on the root “computer” node and selecting “Add legacy hardware”. This should bring up the Add Hardware wizard. Choose the manual, advanced install. Next you should see a list of common hardware types. Select “Network adapters”:
Select Microsoft as the manufacturer and “Microsoft Loopback Adapter” as the network adapter.
Finish out the wizard and it will create a new network device which will appear in your “Network Connections” control panel (ncpa.cpl). It will probably be called something like “Local Area Connection (2)”. I like to rename this to something more descriptive like “loopback” or “Internal Connection”.
Now you can manually assign a static IP address to this connection. Choose something from one of the ranges defined by the IETF as private: 10.0.0.0/8, 172.16.0.0/12 or 192.168.0.0/16.
For my example, I’m going to subnet the 10 network and use 10.237.0.1 mask 255.255.0.0 with no default gateway or DNS servers defined.
At this point, if you are running Windows Vista or 7, you may notice a small problem. The “Internal Connection” device says it is on the “Unidentified Network” which means that Windows thinks you are connected to a “Public Network” which means that Windows Firewall will block Windows File and Printer sharing.
In order to calm Windows down, we need to make a registry change to mark our loopback adapter as an endpoint device. This indicates to Windows that it is not a true network device that connects to an external network. In my opinion, this should be the default setting for the loopback driver, but it isn’t. In order to make this change we need to create the *NdisDeviceType value as DWORD of 1 in the key for our loopback adapter. (See MSDN documentation.)
Network adapters are configured under the following registry key:
The default value on this key is “Network Adapters”. There will be several four-digit number sub-keys (such as 0016) depending on how many network interfaces are installed on your machine. One of these will have a DriverDesc value of “Microsoft Loopback Adapter”.
Once you have found the key for the loopback adapter, add a DWORD value to it called *NdisDeviceType with a DWORD value of 1. Note: common mistake is to leave off the asterisk, which should be included as part of the value name.
Once you have added this value, you must bounce the driver by disabling and enabling your loopback device or reboot for the change to take effect.
The last loopback adapter-related activity is to tell Windows Firewall not to monitor the loopback interface.
In Windows 7, you do this through the advanced settings link of the Firewall control panel applet. Right-click on the root “Windows Firewal with Advanced Security” node and choose properties. You can then set the “Protected Network Connections” for the Domain Profile, Private Profile and Public profile.
In Windows Vista, it is a little easier to get to the dialog. In the Windows Firewall control panel applet, click “Change Settings”.
Step 2: Install a Personal Proxy
Pretty much any lightweight personal proxy server will do for this. I like privoxy which I also use for general ad-blocking across all of my browsers. You can download the latest stable release from privoxy.org.
The privoxy installer is straightforward. Just run it.
Privoxy is essentially a unix-style daemon. It is configured through unixy text files. We need to edit Config.txt located in the Privoxy install directory to tell privoxy to listen on the IP address we bound to our loopback adapter. Privoxy will install into C:\Program Files\Privoxy on x86 Windows or C:\Program Files (x86)\Privoxy on x64 Window.
Look for the listen-address in Config.txt. Set it to the IP address you bound to your loopback adapter and also set the TCP port number to listen on. Privoxy is normally configured to listen on 8118. In my setup, the listen-address is 10.235.0.1:8118.
Finally, we want to configure Privoxy to run as a service so that it will just be there all the time without having to start up its rudimentary GUI. This is how to do it in PowerShell:
PS> ./privoxy --install
PS> set-service privoxy -StartupType Automatic
PS> start-service privoxy
Step 3: Virtual Machines
The hard part is behind us. The rest is pretty easy. We just need to set up Virtual Machines using NAT (shared) networking.
You can get pre-configured virtual machines from Microsoft. These are set up for Virtual PC 2007 but can be run under Sun VirtualBox by just uninstalling the Virtual PC extensions and installing the VirtualBox drivers. On Windows Virtual PC with Windows 7, the XP image is a pain to deal with because Microsoft removed files to compress the image including USB drivers that are useless to VirtualPC 2007 but are essential to Windows Virtual PC. You have to get the drivers back onto the VHD in order to install the Windows Virtual PC extensions. Windows XP Mode is probably a better bet or just install Windows XP from scratch.
Inside of the client OS (probably Windows XP) you just the proxy settings in Internet Options so that HTTP is proxied to 10.237.0.1 port 8118 (or whatever you configured). Uncheck the bypass proxy for local addresses option.
With IE6 in the VM, you can now just go to the same localhost URLs that you use when you launch browsers on your host OS. The one remaining gotcha is that IE7 and IE8 are hard-coded to bypass a proxy server for localhost or 127.0.0.1. They will always bypass a proxy for localhost. The simplest workaround is to put a trailing period after the host name but before the port number so that http://localhost:8080 becomes http://localhost.:8080.
Here’s the whole shebang working with integration features enabled on Windows Virtual PC on Windows 7 x64. This is IE8 on Windows 7 (host OS), IE7 on Windows Vista and IE6 on Windows XP. All three are pointed at the same web project started from Visual Studio 2008. If you look very closely, you just might be able to see the extra period in the URL on IE7.