Hunting Zombies (orphaned IIS Web Applications)
April 25, 2010 Leave a comment
Following on from the previous post, it’s time to look at one of the more sensitive areas of AppFabric… the IIS configuration.
When you run many of the AppFabric configuration commands via Powershell or the IIS Manager, the result is a change to a web.config file. IIS configuration is hierarchical with settings being inherited from parent nodes as we saw with connection strings. The implication of this is that when determining the correct settings for a web application, a series of configuration files are parsed. An error in any one of these configuration files can lead to a broken system. The event logs mentioned in the previous post are a good place to look for these errors, the offending configuration files will often be named in the log entry.
[Update: AppFabric has a one time inheritance model for its configuration, if you choose to provide a configuration setting at a node then this overrides the configuration set at a parent node. The scope / granularity of this is all AppFabric config. Microsoft tried to provide a merged inheritance model but it is a non-trivial problem and did not make v1.]
A common issue on a development workstation is the configuration getting left behind due to poor housekeeping. For example, you map a folder into IIS as a web application, this folder contains other subfolders which in turn are also mapped as web applications. If you remove the parent web application without first removing the child applications then the child configuration remains. It cannot be seen via IIS Manager as there is no way to reach it, however you can easily see it through Powershell. One of the many awesome features in Powershell is the provider model which allows any hierarchical system to be navigated in a consistent way. The canonical example is the file system, we are all used to: cd, dir, etc to navigate around. Well, these same commands (which are actually aliases in Powershell to standard verb-noun commands) can be used to navigate other hierarchies, for example IIS.
From a Powershell console running with elevated status (run as Admin), you can do the following:
First you need to add the IIS Management module to the session:
PS> import-module WebAdministration
You can the navigate the IIS structure by changing the ‘drive’ to be IIS:
> IIS: > ls
Both the dir and ls commands are mapped to get-childitem powershell command via an alias providing a standard Windows console or UNIX console experience. Listing the children at the root level gives us access to the application pools, web sites and SSL bindings. Following through the example above, we navigate to the default web site and then list all of its children. In my case this maps exactly to what is shown in IIS:
Hunting Zombies
So, let’s makes some zombies…
I created a new folder C:\ZombieParent and added two sub folders, ZombieChild1 and ZombieChild2. I then mapped the parent folder to a web application called Zombies and converted the two sub folders also to web applications. Re-running the get-childitem commands now shows:
You can see the three web applications at the end of the list, in IIS Manager we have:
Let’s now remove the parent Zombies web application:
In IIS Manager we no longer see the ZombieChild1 or ZombieChild2 web applications that we can still see via Powershell.
This can be the source of many weird and wonderful errors when working with AppFabric as it tries to parse configuration for zombie web applications. If you are getting strange behavior it is well worth launching a Powershell console and going on a zombie hunt. The web applications left behind can be removed via the console:
Powershell can be a sensitive soul…
I’ll mention another gotcha that tripped me up… case sensitivity. IIS allows you to promote a physical path, to a virtual directory, to a web application. E.g.
> cd \inetpub\wwwroot\ > mkdir test > IIS: > cd '\Sites\Default Web Site' > dir directory test C:\inetpub\wwwroot\test > new-webvirtualdirectory test -physicalpath 'c:\inetpub\wwwroot\test' > dir virtualDirectory test C:\inetpub\wwwroot\test > remove-webvirtualdirectory test > dir directory test C:\inetpub\wwwroot\test
However if the case of the directory/virtual directory/web application does not match exactly then you get the following behavior:
> import-module WebAdministration
> cd \inetpub\wwwroot\
> mkdir test
> IIS:
> cd '\Sites\Default Web Site'
> dir
directory test C:\inetpub\wwwroot\test
> new-webvirtualdirectory Test -physicalpath 'c:\inetpub\wwwroot\test'
> dir
directory test C:\inetpub\wwwroot\test
virtualDirectory Test C:\inetpub\wwwroot\test
> remove-webvirtualdirectory Test
> dir
directory test C:\inetpub\wwwroot\test
virtualDirectory Test C:\inetpub\wwwroot\test
Here we created a new physical directory under the wwwroot folder and then mapped a virtual directory to this location but used a name of Test rather then test. When we get-childitem and we see two entries: ‘test’ for the physical path and ‘Test’ for the virtual directory. Then we remove the virtual directory but it is not deleted and no error is reported.
This caused a heap of confusion for me when automating our deployments so beware of case! This has been raised with Microsoft as an issue. I found that the ConvertTo-WebApplication cmdlet worked for my needs without the case issues.