Group-Object is an awesome cmdlet: it can easily visualize distributions. Check out the examples below:

Get-Process | Group-Object -Property Company
Get-Eventlog -LogName System -EntryType Error | Group-Object -Property Source
Get-ChildItem -Path c:\windows -File | Group-Object -Property Extension

Basically, the cmdlet builds groups based on the content of a given property. You can also omit the group, and just look at the count if all that matters to you are the number distributions:

PS C:\> Get-ChildItem -Path c:\windows -File | Group-Object -Property Extension -NoElement | Sort-Object -Property Count -Descending

Count Name                     
----- ----                     
   10 .exe                     
   10 .log                     
    5 .ini                     
    4 .xml                     
    3 .dll                     
    2 .txt                     
    1 .dat                     
    1 .bin                     
    1 .tmp                     
    1 .prx 

If you are more interested in the actual group of objects, you can ask Group-Object to return a hash table. This way, you can access individual groups via their key:

$hash = Get-ChildItem -Path c:\windows -File | 
  Group-Object -Property Extension -AsHashTable


The result dumps all files in the Windows folder with “.exe” extension. Just be careful if the key (the property you are asking for) is not a string.

Likewise, if you use PowerShell remoting and fan out to multiple computers to retrieve information in parallel, Group-Object can group the results again once you received them. This example retrieves the services from three computers simultaneously, and the results can come back to you in any random order. Group-Object groups the incoming data so that you can process the results per computer. As always with hash tables, you can use brackets or dots to access the hash table keys:

$services = Invoke-Command -ScriptBlock { Get-Service } -ComputerName server1, server2, server3 | Group-Object -Property PSComputerName -AsHashTable


Here is a similar example that seems to have a bug – can you spot the error?

$hash = Get-Service | 
  Group-Object -Property Status -AsHashTable


When you look at the hash table, you would expect to get back the running services:

PS C:\> $hash

Name                           Value                                           
----                           -----                                           
Running                        {AdobeARMservice, AGMService, AGSService, App...
Stopped                        {AJRouter, ALG, AppIDSvc, AppMgmt...} 

However, you don’t get back anything. That’s because the key in this hash table is not a string but rather a “ServiceControllerStatus” object:

PS C:\> $hash.Keys | Get-Member

   TypeName: System.ServiceProcess.ServiceControllerStatus

In order to get back accessible keys, you should always combine -AsHashTable with -AsString. The latter makes sure that a key is always turned into a string. Now the example works as expected:

$hash = Get-Service | 
  Group-Object -Property Status -AsHashTable -AsString


Twitter This Tip! ReTweet this Tip!