Recently I was developing a deployment script – nothing really special (4 web applications + 3 Windows services, main and geo-failover environment). In scope of deployment I need to find running web applications and then start them again (after deploying binaries and configuration). With PowerShell we have the following 2 ways for doing this:
- WMI (against classes in root\MicrosoftIISv2 namespace introduced with IIS 6.0);
- WebAdministration API (introduces with IIS 7.0).
It’s quite unsurprising that both have their own pros and cons:
- Using WMI requires quite some wondering among documentation; getting used to it; knowing and using different classes (not so obvious at times); dealing with security and permissions; respecting the fact that once you’ve obtained an object and did smth (that changes its state) the object you have won’t refresh automatically (i.e. if you have an object that represents a Site and you stopped it, the object you have in your PowerShell session with still be in “Running” state), etc. But overall it’s ok – once you get an idea on how the whole thing works and get over some immediate problems you’ll be up and running with no major problems.
- WebAdministration API at first sight looks easier / more attractive – high level API (cmdlets for PowerShell) with virtual path provider; classes closely reflect objects that we mange in IIS through interface. Second sight, however, reveals some not-so-pleasant details: is packed into a separate dll and PowerShell module (which you need to find / install correctly); no direct option for managing remote instances of IIS; quite a lot of cmdlets (which is comparable in number with WMI classes for IIS 6.0).
A deeper investigation and some testing reveal a few exciting and interesting facts:
- root\MicrosoftIISv2 namespace is actually considered as ‘deprecated’ (since IIS 7.0) and you’ll need to install “IIS 6 WMI compatibility” component in order for it to be available;
- WebAdministration API actually relies on WMI classes underneath (which is good if you managed to master WMI path) which suggests that
- you can use this new way for doing whatever you want;
- potentially you don’t need additional dll and module;
- will seamlessly work for managing remote machines.
All is good indeed, until you realize that new new WMI classes are … well … do not provide you with the functionality that you expect. Microsoft did a good job on providing transition matrix (use this for that, etc), but the point is that new classes add more friction where you would not expect it. For instance, I need to get a list of all running sites (see above). With IIS 6 WMI provider it’s quite straightforward:
-Namespace root\MicrosoftIISv2 `
-ComputerName $currentNode.HostName `
-Authentication PacketPrivacy `
-Query "SELECT * FROM IISWebServer WHERE ServerState = 2"
conditions – that’s why we have SQL-like syntax here, right?
What about new IIS 7 classes? Surprise! Site / application pool state is no longer a property – now it’s a method! Calling GetState() on ApplicationPool or Site is pretty much a no-brainer, but how should I handle that inside a query? No way? Are you kidding? What if I have dozens of sites and I don’t need / want to go through most of them? You don’t care? But that worked perfectly (ok, ok, just worked) for me before, why did you decided to implement new API and deprecate this one just 1 major release after it was shipped? That’s something I don’t understand about Microsoft lately – and this is just one example (with more around Windows Phone, Windows, Office).