Select-Object with Subproperties

Get-Process | Select ProcessName, StartTime.DayOfWeek” – if you ever wanted this notation to work to give you subproperties of objects – read on.🙂

This short notation for subproperties (in this particular case:  StartTime.DayOfWeekto get the DayOfWeek property of process start time) is unfortunately not supported in PowerShell out of the box. Instead you have to type something like: “@{Name=”Start Day”; Expression = {$_.StartTime.DayOfWeek}}” which is kind of long and scary.

Luckily PowerShell 2.0 has so called proxy functions and I have just implemented my overload of Select-Object which add the ability to directly reference subproperties as in the example above. You can find the code at PoshCode here.

Frankly, using PowerShell 2.0 code snippet for proxy functions this was quite trivial to implement. All I have to do was to check whether any Property parameters have dots, and if they do – substitute them with the long and scary expression notation.🙂

In the code below, everything is default output from the snippet except for a dozen of lines after: “#region: Dmitry Sotnikov: substitute dotted properties with expressions

Here’s the code you need to load in your PowerShell session to enhance the Select-Object behavior:

function Select-Object {
[CmdletBinding(DefaultParameterSetName='DefaultParameter')]
param(
  [Parameter(ValueFromPipeline=$true)]
  [System.Management.Automation.PSObject]
  ${InputObject},

  [Parameter(ParameterSetName='DefaultParameter', Position=0)]
  [System.Object[]]
  ${Property},

  [Parameter(ParameterSetName='DefaultParameter')]
  [System.String[]]
  ${ExcludeProperty},

  [Parameter(ParameterSetName='DefaultParameter')]
  [System.String]
  ${ExpandProperty},

  [Switch]
  ${Unique},

  [Parameter(ParameterSetName='DefaultParameter')]
  [ValidateRange(0, 2147483647)]
  [System.Int32]
  ${Last},

  [Parameter(ParameterSetName='DefaultParameter')]
  [ValidateRange(0, 2147483647)]
  [System.Int32]
  ${First},

  [Parameter(ParameterSetName='DefaultParameter')]
  [ValidateRange(0, 2147483647)]
  [System.Int32]
  ${Skip},

  [Parameter(ParameterSetName='IndexParameter')]
  [ValidateRange(0, 2147483647)]
  [System.Int32[]]
  ${Index})

begin
{
 try {
     $outBuffer = $null
     if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
     {
         $PSBoundParameters['OutBuffer'] = 1
     }

     #region: Dmitry Sotnikov: substitute dotted properties with expressions
     if ($Property -ne $null) {
      # Iterate through properties and substitute those with dots
      $NewProperty = @()
      foreach ( $prop in $Property ) {
       if ($prop.GetType().Name -eq 'String') {
        if ($prop.Contains('.')) {
         [String] $exp = '$_.' + $prop
         $prop = @{Name=$prop; Expression = {Invoke-Expression ($exp)}}
        }
       }
       $NewProperty += $prop
      }
      $PSBoundParameters['Property'] = $NewProperty
     }
     #endregion

     $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Select-Object',
         [System.Management.Automation.CommandTypes]::Cmdlet)
     $scriptCmd = {& $wrappedCmd @PSBoundParameters }
     $steppablePipeline =
         $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
     $steppablePipeline.Begin($PSCmdlet)
 } catch {
     throw
 }
}

process
{
    try {
        $steppablePipeline.Process($_)
    } catch {
        throw
    }
}

end
{
    try {
        $steppablePipeline.End()
    } catch {
        throw
    }
}
<#

.ForwardHelpTargetName Select-Object
.ForwardHelpCategory Cmdlet

#>
}

4 Responses to “Select-Object with Subproperties”


  1. 1 Xaegr January 25, 2010 at 5:33 pm

    You can use this shorter notation:
    Get-Process | select processname, {$_.StartTime.DayOfWeek}

    By the way, -ExpandProperty parameter will also benefit from this modification.

    • 2 Dmitry Sotnikov January 25, 2010 at 7:27 pm

      Very cool, I did not know you could just use a scriptblock. Thanks!

      To make this work for -ExpandProperty you can just copy/paste the region – I guess someone needs to do this at poshcode… Maybe I will if I have 10 minutes to do this and test results…


  1. 1 Dew Drop – January 25, 2010 | Alvin Ashcraft's Morning Dew Trackback on January 25, 2010 at 2:28 pm
  2. 2 PowerShell Get-Mailbox display SMTP addresses « Unlock-PowerShell Trackback on January 27, 2010 at 3:15 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




My Recent Tweets

Legal

The posts on this blog are provided “as is” with no warranties and confer no rights. The opinions expressed on this site are mine and mine alone, and do not necessarily represent those of my employer - WSO2 or anyone else for that matter. All trademarks acknowledged.

© 2007-2014 Dmitry Sotnikov

January 2010
M T W T F S S
« Dec   Feb »
 123
45678910
11121314151617
18192021222324
25262728293031

%d bloggers like this: