OdeToCode IC Logo

PowerShell and AppPool Names

Tuesday, July 18, 2006

Yesterday we looked at stopping ASP.NET worker processes using PowerShell. However, I don't always want to stop the process by exe name or process ID, but by the name of the IIS application pool that the process is hosting. One way to do the job is with the iisapp.vbs script that ships with Windows Server.

PS>iisapp.vbs
W3WP.exe PID: 4420   AppPoolId: aspNet20
W3WP.exe PID: 2572   AppPoolId: DefaultAppPool

How does iisapp.vbs figure this out? The script uses WMI to look at the command line that started w3wp.exe. There is a parameter (-ap) that specifies the application pool by name.

I beat my head against the wall trying to figure out a nice way to do this in PowerShell. Finally, I came across a post by abhishek, who wrote some script to find the services living inside svchost.exe, and everything became clear.

function get-aspnetwp([string]$name="*")
{
   $list = get-process w3wp
   foreach($p in $list)
   {
      $filter = "Handle='" + $p.Id + "'"
      $wmip = get-WmiObject Win32_Process -filter $filter

      if($wmip.CommandLine -match "-ap `"(.+)`"")
      {
         $appName = $matches[1]
         $p | add-member NoteProperty AppPoolName $appName
      }
   }
   $list | where { $_.AppPoolName -like $name }
}

This is a function named get-aspnetwp. I can put this in my home configuration so it's always available. The function first gets a list of all processes named w3wp. The System.Diagnostics.Process objects in the list do not expose a property to inspect the command line, but we can use a WMI query to fetch the command line. A regular expression (-match) can parse out the application pool name (which always follows the -ap switch).

The function dynamically adds a property with the add-member cmdlet. The new property (AppPoolName) holds the application pool name. Ah, the power of a dynamic language! The last step in the function is to filter the list of objects against the incoming name parameter.

Now we can party...

PS> get-aspnetwp

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    419      30    31128       3924   144     2.09   2572 w3wp
    387      14    24580       7232   157     1.00   4420 w3wp

and …

PS> get-aspnetwp | select Id, AppPoolName, StartTime | format-list

Id          : 4420
AppPoolName : aspNet20
StartTime   : 7/10/2006 10:31:08 PM

Id          : 6064
AppPoolName : DefaultAppPool
StartTime   : 7/10/2006 11:56:57 PM

and …

PS> get-aspnetwp DefaultAppPool | kill

The little function gives us object we can pipe to other cmdlets, like measure-object, where-object, select-object, etc. Sweetness.

For more PowerShell goodness, check out the Powershell blog, the free IDE, and Scott Hanselman's podcast.