Using Microsoft.Web.Administration in Windows PowerShell

A couple of months ago I wrote about using LINQ with Microsoft.Web.Administration to manage and query IIS 7.0 configuration. Somebody came back to me and said that LINQ was very cool but that it was very much Developer oriented and that in a production server without VS or .NET 3.5 it wouldn't be an option. Indeed that is a very valid comment and so I decided to show similar stuff with a tool that is available in Windows and its more IT oriented, Windows PowerShell.

So in this blog I will quickly mention some of the things you can easily do with Microsoft.Web.Administration inside Windows PowerShell.

To start working with Microsoft.Web.Administration the first thing you need to do is load the assembly so that you can start using it. It is quite easy using the methods from the Assembly type.

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Web.Administration")

Once you have the assembly available then you will need to create an instance of our ServerManager class that gives you access to the entire configuration system.

$iis = new-object Microsoft.Web.Administration.ServerManager

The above line basically declares a variable called $iis that we will be able to use for all of our configuration tasks.

Now to more interesting stuff.

Getting the list of Sites

Getting the list of sites is as easy as just accessing the Sites collection, this will output all the information about sites

PS C:\ > $iis = new-object Microsoft.Web.Administration.ServerManager
PS C:\ > $iis.sites
ApplicationDefaults : Microsoft.Web.Administration.ApplicationDefaults
Applications : {DefaultAppPool, DefaultAppPool, DefaultAppPool, DefaultAppPool...}
Bindings : {}
Id : 1
Limits : Microsoft.Web.Administration.SiteLimits
LogFile : Microsoft.Web.Administration.SiteLogFile
Name : Default Web Site
ServerAutoStart : True
State : Started

However, we can also specify the information we care and the format we want to use, for example:

PS C:\ > $iis = new-object Microsoft.Web.Administration.ServerManager
PS C:\ > $iis.sites | select-object Id, Name, State
Id Name State
-- ---- -----
1 Default Web Site Started
2 Site2 Started
3 Site3 Started

You can also use the where-object command to filter objects to get only the sites that are Stopped, and then we want to Start them.

PS C:\ > $iis = new-object Microsoft.Web.Administration.ServerManager
PS C:\ > $iis.sites | where-object {$_.State -eq "Stopped"} | foreach-object { $_.Start() }

OK, now let's imagine I want to find all the applications that are configured to run in the Default ApplicationPool and move them to run in my NewAppPool. This is better to do it in three lines:

PS C:\ > $iis = new-object Microsoft.Web.Administration.ServerManager
PS C:\ > $iis.sites | foreach {
$_.Applications | where { $_.ApplicationPoolName -eq 'DefaultAppPool' } |
foreach { $_.ApplicationPoolName = 'NewAppPool' }
}
PS C:\ > $iis.CommitChanges()

Now let's say I want to find the top 20 distinct URL's of all the requests running in all my worker processes that has taken more than 1 second.

PS C:\ > $iis = new-object Microsoft.Web.Administration.ServerManager
PS C:\ > $iis.WorkerProcesses | foreach {
$_.GetRequests(1000) | sort TimeElapsed -descending |
select-object Url -unique -first 20 }

OK, finally let's say I want to display a table of all the applications running under DefaultAppPool and display if Anonymous authentication is enabled or not. (Now this one is almost on the edge of "you should do it differently, but it is Ok if you are only reading a single value from the section):

PS C:\ > $iis = new-object Microsoft.Web.Administration.ServerManager
PS C:\ > $iis.Sites | foreach {
$_.Applications | where { $_.ApplicationPoolName -eq 'DefaultAppPool' } |
select-object Path,@{Name="AnonymousEnabled"; Expression = {
$_.GetWebConfiguration().GetSection("system.webServer/security/authentication/anonymousAuthentication").GetAttributeValue("enabled")
}}
}

Again, the interesting thing is that now you can access all the functionality from M.W.A. from Windows PowerShell very easily without the need of compiling code or anything else. It does take some time to get used to the syntax, but once you do it you can do very fancy stuff.