title: Select-Object -ExpandProperty vs. Get-ItemPropertyValue
body: <p>Most likely there's something fundamental I don't understand about PowerShell. I really don't like when writing even medium sized pipes, where grabbing a property breaks the workflow by having to put parens around the statement up to that point, for eg.</p>
  
  <pre><code>(Get-ChildItem ~\.gitconfig).Length
  </code></pre>
  
  <p>This is tedious. Because <code>Length</code> looks very much like a property, one would think</p>
  
  <pre><code>Get-ChildItem ~\.gitconfig | Get-ItemPropertyValue -Name Length
  </code></pre>
  
  <p>would work. However, it does not. Taking a look at the interface of the <code>System.IO.FileSystemInfo</code> object returned by the File System PSDrive provider, one sees that it doesn't have a Length property. It does have a FullName property though, hence</p>
  
  <pre><code>Get-ChildItem ~\.gitconfig | Get-ItemPropertyValue -Name FullName
  </code></pre>
  
  <p>works as expected. To retrieve the size (<code>Length</code>) of a file using the pipe, one has to use <code>Select-Object</code> with the <code>-ExpandProperty</code> like</p>
  
  <pre><code>Get-ChildItem ~\.gitconfig | Select-Object -ExpandProperty Length
  </code></pre>
  
  <p><strong>How does one know up front whether placing a <code>.</code> after an object and iterating through the results of tab completion, if the entry is an object or a property?</strong> It's very annoying that even common operations are confusing as hell, given for instance that reading environmental variables goes by</p>
  
  <pre><code>Get-Item -Path Env:\USERNAME
  </code></pre>
  
  <p>returns</p>
  
  <pre><code>Name                           Value
  ----                           -----
  USERNAME                       mnagy
  </code></pre>
  
  <p>If it's an item, <code>Get-ItemProperty</code> and <code>Get-ItemPropertyValue</code> must play a role here. Because of the Name:Value structure of the result, newcomers might be intrigued to obtain the actual value saying</p>
  
  <pre><code>Get-Item -Path Env:\USERNAME | Get-ItemPropertyValue
  </code></pre>
  
  <p>or actually reading how <code>Get-ItemPropertyValue</code> should be used modify the query to</p>
  
  <pre><code>Get-ItemPropertyValue -Path Env:\ -Name USERNAME
  </code></pre>
  
  <p>which in fact results in</p>
  
  <pre><code>Get-ItemPropertyValue : Cannot use interface. The IPropertyCmdletProvider interface is not supported by this provider.
  At line:1 char:1
  + Get-ItemPropertyValue -Path Env:\ -Name USERNAME
  + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  + CategoryInfo          : NotImplemented: (:) [Get-ItemPropertyValue], PSNotSupportedException
  + FullyQualifiedErrorId : NotSupported,Microsoft.PowerShell.Commands.GetItemPropertyValueCommand
  </code></pre>
  
  <p>This entire construction seems utterly inconsistent to me and most vexing, but hopefully not by design, but because I look at it from the wrong angle.</p>