Question:
To see all pools, their status and their applications inside IIS:\AppPools\
, I use following command in PowerShell:
1 2 |
Get-ChildItem –Path IIS:\AppPools\ |
The output of this command is sorted in 3 columns named “Name“, “State” and “Applications“; It will look like this example:
1 2 3 4 5 6 7 8 9 |
Name State Applications ---- ----- ------------ DefaultAppPool Started item AnotherAppPool Started /item/item AnotherAppPool2 Started /item AppPool XYZ Started item 1 item 2 item 3 ... |
My attempts at this point is to store the output of the command above into a array for later processing; Therefore I wrote following code in PowerShell:
(I annotated every step for better understanding)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
Import-Module WebAdministration # This array contains a hash table with the output of # the command "Get-ChildItem –Path IIS:\AppPools\": $MY_IIS_APPLICATION_POOL = @{}; # "$COUNT" contains index number for each hash table in # "$MY_IIS_APPLICATION_POOL"; It'll increased during # the foreach-loop at its end: $COUNT = 0; # Looping each record/line of the command, to get the # needed informations out of the several columns: foreach ($RECORD in (Get-ChildItem –Path IIS:\AppPools\)) { # Getting the needed records of each line: $POOL_NAME = $RECORD.Name; $POOL_STATUS = $RECORD.State; $POOL_APPS = ""; # If there are more items in column "Applications": if ($RECORD.Applications -is [array]) { foreach ($APP in $RECORD.Applications) { $POOL_APPS = ($APP.ToString() + "," + $POOL_APPS); } } elseif ($RECORD.Applications -eq $NULL) { # Otherwise, if value is empty: $POOL_APPS = "---"; } else { # Or if column contains only one value: $POOL_APPS = $RECORD.Applications.ToString(); } # Defining Hash-Table in $MY_IIS_APPLICATION_POOL: $MY_IIS_APPLICATION_POOL[$COUNT] = @{ 'Name' = $POOL_NAME; 'Status' = $POOL_STATUS; 'Apps' = $POOL_APPS; }; # Increase array index number for next hash table: $COUNT++; } |
This works well – I’m able to get the values by this scheme $MY_ARRAY[0...9].Name
or for the status via $MY_ARRAY[0...9].Status
. But I’m getting empty values by fetching the “Applications” column: $MY_ARRAY[0...9].Apps
is always empty.
So does anybody know how to get the values form the column “Applications”?
Answer:
The reason Applications
is always empty is because this is not actually a property on the object being returned. This data is being created in the console output by an output formatter in the webadministration module.
You can take a look at the properties available if you pipe your app pool object to Get-Member
. You’ll notice that Applications
doesn’t exist as a member. If you grab the full type name from Get-Member
1 2 |
Microsoft.IIs.PowerShell.Framework.ConfigurationElement#system.applicationHost/applicationPools#add |
you can head on over to the webadministration module to take a closer look. Typically you’ll find this at C:\Windows\System32\WindowsPowerShell\v1.0\Modules\WebAdministration
Inside the module you’ll find a file called iisprovider.format.ps1xml
that is handling the output formatting. If you pop that open and search for the type name you’ll find the code that’s running to produce the output you see in the Applications
column. The table column isn’t named so you’ll just have to count to the third column to find it. It looks like this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$pn = $_.Name $sites = get-webconfigurationproperty "/system.applicationHost/sites/site/application[@applicationPool=`'$pn`'and @path='/']/parent::*" machine/webroot/apphost -name name $apps = get-webconfigurationproperty "/system.applicationHost/sites/site/application[@applicationPool=`'$pn`'and @path!='/']" machine/webroot/apphost -name path $arr = @() if ($sites -ne $null) {$arr += $sites} if ($apps -ne $null) {$arr += $apps} if ($arr.Length -gt 0) { $out = "" foreach ($s in $arr) {$out += $s.Value + "`n"} $out.Substring(0, $out.Length - 1) } |
You could pipe the output from Get-ChildItem –Path IIS:\AppPools\
to Out-String
like $appPoolText = Get-ChildItem –Path IIS:\AppPools\ | Out-String
and then parse it but that seems like a lot of work. For my use I just converted the formatter code into a function I could use.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function GetAppsInPool($pn) { $sites = get-webconfigurationproperty "/system.applicationHost/sites/site/application[@applicationPool=`'$pn`'and @path='/']/parent::*" machine/webroot/apphost -name name $apps = get-webconfigurationproperty "/system.applicationHost/sites/site/application[@applicationPool=`'$pn`'and @path!='/']" machine/webroot/apphost -name path $arr = @() if ($sites -ne $null) {$arr += $sites} if ($apps -ne $null) {$arr += $apps} if ($arr.Length -gt 0) { $out = "" foreach ($s in $arr) {$out += $s.Value + "`n"} $out.Substring(0, $out.Length - 1) } } |
You could then technically use that with Select-Object
to create an inline custom object with a calculated property that would look the way you want it to. Something like
Get-ChildItem IIS:\AppPools\ | select Name,State,@{n='Applications';e={GetAppsInPool -pn $_.Name}}