Accessing Microsoft.Web.Administration through PowerShell (Part I)

I've caught the PowerShell bug. In between stints with my ever-expanding code samples, I play with PowerShell a lot.  I thought I'd share a quick example of how to load Microsoft.Web.Administration.dll and use it to perform some basic tasks.

Note: I'm running these samples on Windows Vista RTM, but I have no reason to believe this will not work on the PowerShell release candidates for the Vista RC* builds that are available now

So let's get started.

First, PowerShell has no idea where Microsoft.Web.Administration.DLL is so you have to tell it how to load it. Anyone who has written code to dynamically load an assembly should be familiar with this syntax.  Type the following command

PS C:\> [System.Reflection.Assembly]::LoadFrom( "C:\windows\system32\inetsrv\Microsoft.Web.Administration.dll" )

The path to your assembly may change depending on your install.  I'll show you later how to use environment variables to calculate the correct path.  In the mean time the out put of the line above display something like the following:

GAC  Version    Location
---  -------    --------
True v2.0.50727 C:\Windows\assembly\GAC_MSIL\Microsoft.Web.Administration\7.0.0.0__31bf3856ad364e35\Microsoft....

Once the assembly is loaded you can use PowerShell's "New-Object" command to create a ServerManager object that is defined in Microsoft.Web.Administration.

PS C:\> (New-Object Microsoft.Web.Administration.ServerManager)

This doesn't give you much except the list of properties the ServerManager exposes:

ApplicationDefaults      : Microsoft.Web.Administration.ApplicationDefaults
ApplicationPoolDefaults  :
ApplicationPools         :
SiteDefaults             : Microsoft.Web.Administration.SiteDefaults
Sites                    : {Default Web Site}
VirtualDirectoryDefaults : Microsoft.Web.Administration.VirtualDirectoryDefaults
WorkerProcesses          : {}

To get more detail, you need to use the properties and methods of the ServerManager object to drill down and get the information we want. The ServerManager provides access to all of the sites on your machine through a SiteCollection object. This SiteCollection is made available through the "Sites" property of the ServerManager. 

PS C:\> (New-Object Microsoft.Web.Administration.ServerManager).Sites

Which will produce a list view of all the sites and their associated property names/values.

ApplicationDefaults        : Microsoft.Web.Administration.ApplicationDefaults
Applications               : {DefaultAppPool, Classic .NET AppPool}
Bindings                   : {}
Id                         : 1
Limits                     : Microsoft.Web.Administration.SiteLimits
LogFile                    : Microsoft.Web.Administration.SiteLogFile
Name                       : Default Web Site
ServerAutoStart            : True
State                      : Started
TraceFailedRequestsLogging : Microsoft.Web.Administration.SiteTraceFailedRequestsLogging
VirtualDirectoryDefaults   : Microsoft.Web.Administration.VirtualDirectoryDefaults
ElementTagName             : site
IsLocallyStored            : True
RawAttributes              : {name, id, serverAutoStart}

ApplicationDefaults        : Microsoft.Web.Administration.ApplicationDefaults
Applications               : {DefaultAppPool}
Bindings                   : {}
Id                         : 2
Limits                     : Microsoft.Web.Administration.SiteLimits
LogFile                    : Microsoft.Web.Administration.SiteLogFile
Name                       : Test Web Site 1
ServerAutoStart            : False
State                      : Stopped
TraceFailedRequestsLogging : Microsoft.Web.Administration.SiteTraceFailedRequestsLogging
VirtualDirectoryDefaults   : Microsoft.Web.Administration.VirtualDirectoryDefaults
ElementTagName             : site
IsLocallyStored            : True
RawAttributes              : {name, id, serverAutoStart}

Of course, this isn't the easiest view to read, so let's say we just list the site names by piping our site list to the "ForEach-Object" command in PowerShell and display a list of site names only:

 PS C:\> (New-Object Microsoft.Web.Administration.ServerManager).Sites | ForEach-Object {$_.Name}

This looks much more concise:

Default Web Site
Test Web Site 1

We could also use the Select-Object syntax to query the list into a table format:

 PS C:\> (New-Object Microsoft.Web.Administration.ServerManager).Sites | Select Id, Name

        Id Name
        -- ----
         1 Default Web Site
         2 Test Web Site 1

Now lets use PowerShell to manage application pools. We can fit several commands on one line by using the semi-colon.  The following command-line is actually four different operations: Storing the application pool collection into a variable, displaying the name and runtime status of the first application pool, stopping the first application pool, then displaying the name and status again.

PS C:\> $pools=(New-Object Microsoft.Web.Administration.ServerManager).ApplicationPools; $pools.Item(0) | Select Name, State;$pools.Item(0).Stop(); $pools.Item(0) | Select Name, State

Running this sample should display the following:

Name                                         State
----                                         -----
DefaultAppPool                               Started
Stopped
DefaultAppPool                               Stopped

This is nice, but we can do this already with appcmd.exe right? Well, to some extent.  We don't get the features of PowerShell that allow us to format our output the data to our liking. Also, as a developer, I find it much easier to use the API syntax I'm already familiar with than to remember appcmd.exe syntax.  Furthermore, PowerShell allows us to use WMI alongside our managed code calls, and unlike appcmd.exe, you can extend PowerShell and cmdlets. PowerShell gives you the ability to easily manage multiple servers from one command prompt on one machine.  Watch the PowerShell/IIS 7 interview on Channel9 if you want to see this remote administration in action.

One last thing that PowerShell brings to the table is the ability to "spot-weld" our object models (as Scott Hanselman quipped). You can create/modify/extend type data and formatting to your hearts desire.  For more information on this, check out the PowerShell documentation found in the PowerShell install, or in the PowerShell documentation set.

So, I would be remiss in this post if I didn't try to make your PowerShell / IIS 7.0 life easier.  As such, I've created a profile script that loads all the IIS 7.0 managed assemblies for you.  The script is simple and contains more  echo commands than actual working script lines.

To install this script run the following command inside PowerShell:

PS C:> if ( test-path $profile ) { echo "Path exists." } else { new-item -path $profile -itemtype file -force }; notepad $profile

This will create a profile path for you if you don't already have one, then open up your profile in notepad.  If you haven't added anything to the file, it will obviously display an empty file.  Paste the following in notepad when it opens:

echo "Microsoft IIS 7.0 Environment Loader"
echo "Copyright (C) 2006 Microsoft Corporation. All rights reserved."
echo "  Loading IIS 7.0 Managed Assemblies"

$inetsrvDir = (join-path -path $env:windir -childPath "\system32\inetsrv\")
Get-ChildItem -Path (join-path -path $inetsrvDir -childPath "Microsoft*.dll") | ForEach-Object {[System.Reflection.Assembly]::LoadFrom( (join-path -path $inetsrvDir -childPath $_.Name)) }

echo "  Assemblies loaded."

Now, save the profile and close notepad.  You will likely have to sign this script or change your script execution policy to something very weak to make this script run properly (obviously I'm not recommending the latter). To find out more about signing scripts, type "get-help about_signing" in PowerShell. The instructions to create a self-signed certificate found in that help file are as follows:

In an SDK Command Prompt window, run the following commands.
The first command creates a local certificate authority for your computer.
The second command generates a personal certificate from the certificate authority:

makecert -n "CN=PowerShell Local Certificate Root" -a sha1 `
   -eku 1.3.6.1.5.5.7.3.3 -r -sv root.pvk root.cer `
   -ss Root -sr localMachine
makecert -pe -n "CN=PowerShell User" -ss MY -a sha1 `
   -eku 1.3.6.1.5.5.7.3.3 -iv root.pvk -ic root.cer
   MakeCert will prompt you for a private key password.

Go ahead and make a certificate for yourself following those instructions. To sign your profile, within PowerShell type the following:

PS C:\>Set-AuthenticodeSignature $profile @(get-childitem cert:\CurrentUser\My -codesigning)[0]

So far, you've created a certificate and signed your script. Now, you will have to change your script execution policy down at least one level from the default.  The default doesn't allow scripts at all.  To get scripts to execute, at the minimum you'll have to set it to "AllSigned" to allow only signed scripts to execute.  In this mode, each time you execute a script from a new publisher, you'll be asked what level of trust to assign to the publisher (unless you respond to the prompt to "Always Run" or "Never Run" scripts from that publisher)

Do you want to run software from this untrusted publisher?
File C:\Users\TobinT\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 is published by CN=PowerShell User
and is not trusted on your system. Only run scripts from trusted publishers.
[V] Never run  [D] Do not run  [R] Run once  [A] Always run  [?] Help (default is "D"):

Now, each new instance of PowerShell that you run will automatically load the IIS 7.0 managed assemblies.  I know it seems like a great deal of work, but it really isn't once you've made a few rounds around inside PowerShell. Consider that you only have to create the script once and then you have full the full range of the managed IIS 7.0 SDK at your fingertips inside PowerShell. 

If you have problems, feel free to leave comments and I'll do my best to help you.

Published Thursday, November 30, 2006 8:09 PM by TobinTitus

Comments

# re: Accessing Microsoft.Web.Administration through PowerShell

Friday, December 01, 2006 6:37 AM by bills

nice post!

# re: Accessing Microsoft.Web.Administration through PowerShell

Friday, December 01, 2006 10:44 AM by TobinTitus

Thank you sir.  I just "updated" the post because the language was a bit hard to read.  That's what happens when you start a post at 8:00pm, then get playing around with PowerShell and start the post back up at er... 2am :)

# Extending Microsoft.Web.Administration through PowerShell (Part II)

Friday, December 01, 2006 2:33 PM by Tobin Titus Blog

In my previous post , I showed you how easy it was to leverage your knowledge of the IIS 7 managed SDK

# Accessing Microsoft.Web.Administration through PowerShell (Part I)

Friday, December 01, 2006 2:45 PM by Tobin Titus

I've caught the PowerShell bug. In between stints with my ever-expanding code samples, I play with PowerShell

# I have got the power!!

Saturday, December 02, 2006 12:46 AM by Server: Microsoft-IIS/7.0\r\n

Hehe :) Not just me! You have got the power as well.... to manage IIS via PowerShell. Honestly, I'm not

# IIS7 - post - #27 - Powershell & Microsoft IIS Web.administration blog

Saturday, January 13, 2007 11:18 PM by Steve Schofield Weblog

Found this blog by Tobin Titus . Definitely check it out! http://blogs.iis.net/tobintitus/archive/2006/11/30/powershell-and-microsoft-web-administration.aspx

# IIS7 - post #27 - Powershell & Microsoft IIS Web.administration blog

Sunday, January 14, 2007 12:51 AM by Steve Schofield's Blog

Found this blog by Tobin Titus . Definitely check it out! http://blogs.iis.net/tobintitus/archive/2006/11/30/powershell-and-microsoft-web-administration.aspx

# re: Accessing Microsoft.Web.Administration through PowerShell (Part I)

Tuesday, May 29, 2007 1:58 AM by Andrew I.

Hello! Very interesting! Thank you.

# re: Accessing Microsoft.Web.Administration through PowerShell (Part I)

Saturday, June 30, 2007 4:39 AM by Theedrich Yeat

I'm just starting out in PowerShell, and can’t get it to run any script (script1.ps1, which I've downloaded), in spite having used your code, above, to sign it.  I also don’t know how to change my PS’s execution policy in any way.  How do you do that?

# 【收藏】本周ASP.NET英文技术文章推荐[12/03 - 12/09](

Tuesday, October 30, 2007 11:08 PM by Jacky_xu

摘要

昨天诸事不顺,早晨起来肠胃开始不舒服。下午坚持写好本篇推荐文章之后,还没发布居然鬼使神差一般就把草稿删除了?!WindowsLiveWriter处理数据安全方面确实有一套,删除的草稿无论用...

# PowerShell and IIS 7

Friday, January 04, 2008 5:06 AM by PowerShell for Everyone

The introduction of IIS 7 with Windows 2008 brings a managed code (.NET) API for IIS. This means we can administer it through PowerShell. Add the remoting features of V2 and you have a very powerful ...

# re: Accessing Microsoft.Web.Administration through PowerShell (Part I)

Monday, April 21, 2008 7:01 PM by Kanien

how do you delete sites with this?

Leave a Comment

(required) 
(required) 
(optional)
(required) 
Powered by Community Server (Commercial Edition), by Telligent Systems