I've been working on the installation tooling for our web application product recently, finally getting round to upgrading it with IIS7 support. The setup tool is used to deploy different versions of our app onto sales demo and training machines, as well as onto real servers, so it has to handle a wide range of different deployment scenarios. We have to support deploying the .NET 1.1 or 2.0 versions of our code, onto anything from IIS 5.0 on a Windows Server 2000 machine to IIS 7.0 on Windows Server 2008, or onto desktop environments from IIS 5.1 on Windows XP to IIS 7.0 on Vista. And we can't assume .NET or IIS will be installed before our tool runs.
This week, I've been concentrating on dealing with determining if prerequisites are met for installation. Obviously, one prerequisite for the application is that IIS must be present. With IIS 5 or 6, we could look for IIS as a monolithic component, and assume that if we could find evidence of its presence, then the whole thing was installed. IIS7 changes the game, with a slew of individual optional components that can be installed. Just because IIS is there, doesn't mean all the features we require are.
So the first question facing our installer when it finds itself on a system where IIS7 is the supported server - I'm diagnosing that condition with a check for a CurrentVersion of 6.0 or greater at the moment - is to see if the components we rely upon are already installed.
On Windows Server 2008, it looks like we'd be able to ask a program called oclist.exe (it lists optional components, hence, Optional Component List) and determine which IIS features are present. But on Vista, sadly, no such toy is present. We have the analagous installation tool, ocsetup.exe, which installs optional components for us; we also have a related - more granular - tool called pkgmgr.exe, which manages the installed optional feature packages. And we have the GUI tool, optionalfeatures.exe, which allows us to manage installed packages through a nice tree view.
But there's no way to determine using these tools what's already installed. To find that out, after a lot of googling, I finally found that I need to be looking in the registry under HKEY_LOCAL_MACHINE\Software\Microsoft\InetStp\Components.
So, let's say I want to see if ASP.NET support is installed on the system. We need to look in that registry location for a key called 'ASPNET'. If we don't find it, then we know ASP.NET isn't installed, and we can then use pkgmgr.exe to install ASP.NET. pkgmgr.exe calls the ASP.NET component IIS-ASPNET, so we would use the command:
pkgmgr.exe /iu:IIS-ASPNET
So far so good. Except that the IIS-ASPNET module is a child of IIS-ApplicationDevelopment, which belongs to IIS-WebServer, and that is part of the overall IIS-WebServerRole feature. If these are not already installed, we have to specify them on pkgmgr.exe's command line also:
pkgmgr.exe /iu:IIS-ASPNET;IIIS-ApplicationDevelopment;IS-WebServer;IIS-WebServer
Role
And on top of that hierararchical dependency chain, there are also cross-dependencies. IIS-ASPNET directly requires modules called IIS-DefaultDocument, IIS-NetFxExtensibility, IIS-ISAPIExtensions, IIS-ISAPIFilter, IIS-RequestFiltering and WAS-NetFxEnvironment (this is all documented here). And all of these modules have dependencies of their own. In fact, unless you know any of them are already installed, the command to install IIS-ASPNET would be:
pkgmgr.exe /iu:IIS-ASPNET;IIS-ApplicationDevelopment;IIS-WebServer;IIS-WebServer
Role;WAS-ProcessModel;WAS-WindowsActivationService;WAS-NetFxEnvironment;IIS-Requ
estFiltering;IIS-Security;IIS-ISAPIFilter;IIS-ISAPIExtensions;IIS-NetFxExtensibi
lity;IIS-DefaultDocument;IIS-CommonHttpFeatures
Worse, even if all of these modules were already present, the command will take a considerable amount of time to run. And require an administrative elevation even if it has nothing to do. So running the command 'just to make sure' that the prerequisites are installed isn't really the best option.
So I've taken matters into my own hands and put together a command line tool to help. The tool does three things:
- calculates the package dependency list for a given list of required features
- determines which IIS features are currently installed
- runs
pkgmgr.exe for you with the necessary arguments to ensure a particular list of features are supported.
The tool's called IIS7.cmd. Here's some examples of its use:
c:\tools>iis7
IIS-WebServerRole [INSTALLED]
IIS-WebServer [INSTALLED]
IIS-CommonHttpFeatures [INSTALLED]
IIS-StaticContent [INSTALLED]
IIS-DefaultDocument [INSTALLED]
IIS-DirectoryBrowsing
IIS-HttpErrors [INSTALLED]
IIS-HttpRedirect
IIS-ApplicationDevelopment
IIS-ASPNET
IIS-NetFxExtensibility
IIS-ASP
IIS-CGI
IIS-ISAPIExtensions
IIS-ISAPIFilter
IIS-ServerSideIncludes
IIS-HealthAndDiagnostics [INSTALLED]
IIS-HttpLogging [INSTALLED]
IIS-LoggingLibraries
IIS-RequestMonitor [INSTALLED]
IIS-HttpTracing
IIS-CustomLogging
IIS-ODBCLogging
IIS-Security
IIS-BasicAuthentication
IIS-WindowsAuthentication
IIS-DigestAuthentication
IIS-ClientCertificateMappingAuthentication
IIS-IISCertificateMappingAuthentication
IIS-URLAuthorization
IIS-RequestFiltering
IIS-IPSecurity
IIS-Performance [INSTALLED]
IIS-HttpCompressionStatic [INSTALLED]
IIS-HttpCompressionDynamic
IIS-WebServerManagementTools [INSTALLED]
IIS-ManagementConsole [INSTALLED]
IIS-ManagementScriptingTools
IIS-ManagementService
IIS-IIS6ManagementCompatibility
IIS-Metabase
IIS-WMICompatibility
IIS-LegacyScripts
IIS-LegacySnapIn
IIS-FTPPublishingService
IIS-FTPServer
IIS-FTPManagement
WAS-WindowsActivationService [INSTALLED]
WAS-ProcessModel [INSTALLED]
WAS-NetFxEnvironment [INSTALLED]
WAS-ConfigurationAPI [INSTALLED]
Here we're calling the tool with no arguments, and it's showing us that we have a basic IIS system installed. The command output shows the dependency hierarchy (it's similar to the tree structure shown by optionalfeatures.exe).
So let's ask the command what we'd need to install to get ASP.NET working on this machine:
c:\tools>iis7 /q IIS-ASPNET
IIS-ASPNET;IIS-ApplicationDevelopment;IIS-WebServer;IIS-WebServerRole;WAS-Proces
sModel;WAS-WindowsActivationService;WAS-NetFxEnvironment;IIS-RequestFiltering;II
S-Security;IIS-ISAPIFilter;IIS-ISAPIExtensions;IIS-NetFxExtensibility;IIS-Defaul
tDocument;IIS-CommonHttpFeatures
We're specifying the '/q' switch to query dependencies. That's the full list of dependencies, not taking into account what we already have installed. To get the list of just what's missing from the current system, we can use the capitalised switch, /Q:
c:\tools>iis7 /Q IIS-ASPNET
IIS-ASPNET;IIS-ApplicationDevelopment;IIS-RequestFiltering;IIS-Security;IIS-ISAP
IFilter;IIS-ISAPIExtensions;IIS-NetFxExtensibility
Note that if we'd requested the outstanding dependencies for a feature that's already installed, we'd have got a blank output:
c:\tools>iis7 /Q IIS-DefaultDocument
c:\tools>
That provides us with that quick prerequisite check we were after. Is this feature present? If it is, empty response. If not, we'll get a list of everything we need to install to make it present.
If we want to go ahead an run the install, we can do so directly with the /I switch:
c:\tools>iis7 /I IIS-ASPNET
Installing modules.
Installation succeeded.
Behind the scenes, that command runs
pkgmgr.exe /iu:IIS-ASPNET;IIS-ApplicationDevelopment;IIS-RequestFiltering;IIS-Sec
urity;IIS-ISAPIFilter;IIS-ISAPIExtensions;IIS-NetFxExtensibility
i.e., it passes the minimal set of packages to install.
As well as individual packages, we can supply a list of packages we want to ensure. If we wanted ASP.NET and Server-side includes, we could specify both:
c:\tools>iis7 /I IIS-ASPNET IIS-ServerSideIncludes
The configuration file (from which the tool reads all the information it needs to know about package interdependencies) also contains several predefined 'installations', which are lists of standard module sets. So, for an application that needs a basic web server with ASP.NET and Metabase support, you could use the predefined installation sets:
c:\tools>iis7 /I Basic ASP.NET Metabase
And you can mix and match installations and module names. To add dynamic compression to the above configuration:
c:\tools>iis7 /I Basic ASP.NET Metabase IIS-HttpCompressionDynamic
The iis7.cmd file itself is just a wrapper around a Windows Script Host iis7.js script to simplify the command line syntax (you don't want to be typing cscript /nologo every time you run it). The dependency information (and the mapping from pkgmgr module IIS-* module name to HKLM Components registry key names, which aren't always the same) is all contained in iis7.xml.
If you want to take a look, I've posted a zip for download.