PowerShell Snap-in: Run-time Data
by Thomas Deml
The previous walkthroughs showed you how to query and change IIS configuration settings. There is one unexplored area left however: run-time data.
Introduction
Things change, IIS is not different. Sites get started or stopped, Application Pools recycle or time out, requests come in and responses get sent, AppDomains get spawned or shut down. IIS implements an interface called RSCA (run-time state and control API) that allows you to monitor what's going on in the system.
The IIS PowerShell Snap-in uses this interface and exposes some of its data via the IIS Snap-in namespace. The state of Sites and Application Pools is configurable via the Get-WebItemState, Start-WebItem, Stop-WebItem and Restart-WebItem cmdlets. Run-time state like currently running worker processes, currently executing requests and loaded AppDomains is exposed via the IIS namespace.
This walkthrough uses the sites, applications and virtual directories that were created in a previous walkthrough.
Sites and Application Pool State
We're starting by querying the state of our web-sites.
Site State
PS IIS:\> cd Sites
PS IIS:\Sites> Get-WebItemState IIS:\Sites\DemoSite
Started
Stopping DemoSite can be achieved with the Stop-WebItem cmdlet:
PS IIS:\Sites> Stop-WebItem DemoSite
PS IIS:\Sites> Get-WebItemState IIS:\Sites\DemoSite
Stopped
Starting works the same of course:
PS IIS:\Sites> Start-WebItem DemoSite
PS IIS:\Sites> Get-WebItemState IIS:\sites\DemoSite
Started
AppPool State
We want to do the same for Application Pools
PS IIS:\> cd AppPools
PS IIS:\AppPools> Get-WebItemState DemoAppPool
Started
PS IIS:\AppPools> Stop-WebItem DemoAppPool
PS IIS:\AppPools> Get-WebItemState DemoAppPool
Stopped
But there is also the state property you can read on the AppPools node. Let's have some fun with the next example. Turn your speakers on and execute the following command:
dir 'iis:\AppPools' | foreach {[void](new-object -com Sapi.SPVoice).Speak("Application Pool State:");}{$poolState = "Application Pool " + $_.Name +" is " + $_.State;$poolState;[void](new-object -com Sapi.SPVoice).Speak($poolState);}
Now start DemoAppPool again:
PS IIS:\AppPools> Start-WebItem DemoAppPool
Recycling AppPools
The one difference with AppPools is that they can be recycled. The cmdlet to recycle AppPools is called Restart-WebItem and not Recycle-WebItem. PowerShell has pretty strict naming rules and we had to settle for Restart-WebItem. Let's expand this example a little bit by
- Making a request to the default page of the 'Default Web Site'.
- Querying the PID of the worker process is that handles the request.
- Recycling the Application Pool.
- Requesting the PID again to confirm that the process was restarted.
1. Requesting the default page
We use the Net.WebClient class to request http://localhost/
. Instead of displaying the output on the screen we are just looking at the length of the response.
PS IIS:\AppPools> $response = (new-object Net.WebClient).DownloadString("http://localhost/")
PS IIS:\AppPools> $response.Length
689
2. Querying the Worker Process PID
Assuming you have no other active web sites and applications on your machine the following command should return only one PID:
PS IIS:\AppPools> get-process w3wp | select processname,id
ProcessName Id
----------- --
w3wp 3684
There is a better way to get to worker processes, handled a little later in this walkthrough.
3. Recycling the Application Pool
We recycle the Application Pool by using the Restart-WebItem cmdlet:
PS IIS:\AppPools> Restart-WebItem DefaultAppPool
4. Querying for the Worker Process PID
If the AppPool was successfully recycled your Process ID should have been changed.
PS IIS:\AppPools> get-process w3wp | select processname,id
ProcessName Id
----------- --
w3wp 5860
Worker Processes and Requests
The get-process cmdlet doesn't help you figuring out which Application Pool a particular worker process is serving. This can be easily done however:
PS IIS:\AppPools> dir DefaultAppPool\WorkerProcesses
processId Handles state StartTime
--------- ------- ----- ---------
6612 326 1 3/28/2008 12:20:27 PM
Currently Executing Requests
If your machine is not a production machine you will have a hard time looking at currently executing requests. The request is long gone until you make a request via Internet Explorer and get back into the PowerShell console. Here is a little helper; a request that takes a long time.
Set-Content "$env:systemdrive\inetpub\wwwroot\long.aspx" "<%@ Page language=`"C#`"%><%System.Threading.Thread.Sleep(30000);Response.Write(`"slept for 30 seconds`");%>"
If you want to look at the currently executing requests you can type the following command (NOTE: the process id you have to use for the get-item command will be different on your machine):
PS IIS:\AppPools\DefaultAppPool\WorkerProcesses> dir
Process State Handles Start Time
Id
-------- ----- ------- ----------
6612 Running 737 3/31/2008 8:18:15 AM
PS IIS:\AppPools\DefaultAppPool\WorkerProcesses> (get-item 6612).GetRequests(0).Collection
requestId : d8000001800000f5
connectionId : d8000001600000f3
verb : GET
url : /long.aspx
siteId : 1
Or if you want to see how much time already passed since you started the request:
PS IIS:\AppPools\DefaultAppPool\WorkerProcesses> (get-item 6612).GetRequests(0).Collection | select url,timeElapsed
url timeElapsed
--- -----------
/long.aspx 2637
Summary
Done. In this walkthrough you learned how to query the state of IIS Application Pools and Sites. You found out how to start and stop them. You also learned how to look at worker processes and currently executing requests.