Sorting out -GroupBy

PowerShell Team

Did you realize that Format-Table had a parameter -GroupBy?  This tells Format-Table to generate a series of tables instead of a single table.  The best way to get this in focus is to show an example. 

For the purposes of this blog entry, I’m going to use the aliases GSV for Get-Service and FT for Format-Table.  Also, I don’t want too much data for the examples so I’m going to leverage the fact that GSV supports wildcards and specify s[p-z]*  which says give me all the services that start with “s” and whose second character is between “p” and “z” inclusive.  There is nothing special about this, I just did some quick experimentation and that seemed to produce a reasonable dataset for this blog (and it allows me to show off wildcarding in GSV 🙂 ).

First let’s look at the output of GSV and then explore what additional information is available:

PS> gsv s[p-z]* |ft

Status   Name               DisplayName
——   —-               ———–
Running  Spooler            Print Spooler
Stopped  SQLBrowser         SQL Server Browser
Stopped  SQLWriter          SQL Server VSS Writer
Running  SRUserService      IT Connection Manager
Running  SSDPSRV            SSDP Discovery
Running  stisvc             Windows Image Acquisition (WIA)
Stopped  swprv              Microsoft Software Shadow Copy Prov…
Running  SysMain            Superfetch

PS> gsv s[p-z]* |Get-Member -MemberType Property

   TypeName: System.ServiceProcess.ServiceController

Name                MemberType Definition
—-                ———- ———-
CanPauseAndContinue Property   System.Boolean CanPauseAndContinue {get;}
CanShutdown         Property   System.Boolean CanShutdown {get;}
CanStop             Property   System.Boolean CanStop {get;}
Container           Property   System.ComponentModel.IContainer Containe…
DependentServices   Property   System.ServiceProcess.ServiceController[]…
DisplayName         Property   System.String DisplayName {get;set;}
MachineName         Property   System.String MachineName {get;set;}
ServiceHandle       Property   System.Runtime.InteropServices.SafeHandle…
ServiceName         Property   System.String ServiceName {get;set;}
ServicesDependedOn  Property   System.ServiceProcess.ServiceController[]…
ServiceType         Property   System.ServiceProcess.ServiceType Service…
Site                Property   System.ComponentModel.ISite Site {get;set;}
Status              Property   System.ServiceProcess.ServiceControllerSt…

 

Notice that the ServiceController objects emitted by Get-Service (GSV) contain the field ServiceType .  Let’s do this again but this time have Format-Table Group the services by ServiceType:

PS> gsv s[p-z]* |ft -GroupBy ServiceType

   ServiceType: Win32OwnProcess, InteractiveProcess

Status   Name               DisplayName
——   —-               ———–
Running  Spooler            Print Spooler

   ServiceType: Win32OwnProcess

Status   Name               DisplayName
——   —-               ———–
Stopped  SQLBrowser         SQL Server Browser
Stopped  SQLWriter          SQL Server VSS Writer
Running  SRUserService      IT Connection Manager

   ServiceType: Win32ShareProcess

Status   Name               DisplayName
——   —-               ———–
Running  SSDPSRV            SSDP Discovery

   ServiceType: Win32OwnProcess

Status   Name               DisplayName
——   —-               ———–
Running  stisvc             Windows Image Acquisition (WIA)
Stopped  swprv              Microsoft Software Shadow Copy Prov…

   ServiceType: Win32ShareProcess

Status   Name               DisplayName
——   —-               ———–
Running  SysMain            Superfetch

Now you get a series of tables. 

But wait.  Take a close look at those tables.  Notice that you have 2 tables for both Win32ShareProcess and Win32OwnProcess.  The reason for that is that is that Format-Table (ft) is STREAM-ORIENTED.  By that I mean that it gets an object and processes it and then moves on to the next.  It does that so that it doesn’t have to keep all the objects in memory.  When it is done with the object, it is done with the object. 

The only exception to this is when you specify -AutoSize . This tells Format-Table to collect all the objects and calculate the optimal column widths.

So the results we got are not quite what we wanted.  The solution is to sort the object stream prior to sending it to Format-Table (Yes yes yes – let me preempt the question – given these semantics we could have chosen to do the sort in Format-Table.  The reason we didn’t is that it would be wasteful if the stream was already properly sorted).  So lets see what that looks like:

PS> gsv s[p-z]* |Sort ServiceType |ft -GroupBy ServiceType

   ServiceType: Win32OwnProcess

Status   Name               DisplayName
——   —-               ———–
Stopped  SRUserService      IT Connection Manager
Running  stisvc             Windows Image Acquisition (WIA)
Stopped  swprv              Microsoft Software Shadow Copy Prov…
Stopped  SQLBrowser         SQL Server Browser
Stopped  SQLWriter          SQL Server VSS Writer

   ServiceType: Win32ShareProcess

Status   Name               DisplayName
——   —-               ———–
Running  SysMain            Superfetch
Running  SSDPSRV            SSDP Discovery

   ServiceType: Win32OwnProcess, InteractiveProcess

Status   Name               DisplayName
——   —-               ———–
Running  Spooler            Print Spooler

Now that is much better but notice that within a table, things are not sorted by Status.  No problem.  Did you realize that sort can do a multi-key sort?  After we sort by Status, we’ll figure out that we also want it sorted by Name as well so let’s do it all at once shall we?

PS> gsv s[p-z]* |Sort ServiceType,Status,Name |ft -GroupBy ServiceType

   ServiceType: Win32OwnProcess

Status   Name               DisplayName
——   —-               ———–
Stopped  SQLBrowser         SQL Server Browser
Stopped  SQLWriter          SQL Server VSS Writer
Stopped  SRUserService      IT Connection Manager
Stopped  swprv              Microsoft Software Shadow Copy Prov…
Running  stisvc             Windows Image Acquisition (WIA)

   ServiceType: Win32ShareProcess

Status   Name               DisplayName
——   —-               ———–
Running  SSDPSRV            SSDP Discovery
Running  SysMain            Superfetch

   ServiceType: Win32OwnProcess, InteractiveProcess

Status   Name               DisplayName
——   —-               ———–
Running  Spooler            Print Spooler

Cheers! 

Jeffrey Snover [MSFT]
Windows PowerShell/MMC Architect
Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

0 comments

Discussion is closed.

Feedback usabilla icon