title: Powershell implicitly converting arrays preventing use with Select -Property in v2
body: <p>I am struggling with powershell implicitly modifying the structure of the data in <strong>powershell 2 exclusively</strong>. The same logic works fine in powershell 4. </p>
  
  <p>I've created a helper function that given a field, an alias and/or a block expression i can then feed this into a second function that builds a name/expression array which can be passed to a Select -Property request. this worked fine in powershell 4 however i'm working in a mixed environment and when i tried to use it on a powershell 2 server the script failed returning a datatype conversion error.</p>
  
  <pre><code>Cannot convert System.Management.Automation.PSObject to one of the following types {System.String, System.Management.Automation.ScriptBlock}.
  + CategoryInfo          : InvalidArgument: (:) [Select-Object], NotSupportedException
  + FullyQualifiedErrorId : DictionaryKeyUnknownType,Microsoft.PowerShell.Commands.SelectObjectCo    mmand
  + PSComputerName        : ####
  </code></pre>
  
  <p>i now have to basically rebuild the array in the calling function because even an explicit conversion to array raises the same exception.</p>
  
  <pre><code>if ($PSVersionTable["PSVersion"].Major -eq 2)
  {
      #write-host "rebuilding setting"
      $origprops = [System.Array](Get-SelectPropertyArray2 $propsToSelect)
      $props = @()
      for ($i =0 ; $i -lt $origprops.Count ; $i++)
      {
          #write-host $i
          $props += @{n=([System.Array]$origprops)[$i]["n"];e=(([System.Array]$origprops)[$i]["e"])}
      }
  }
  </code></pre>
  
  <p>The following is insufficient:</p>
  
  <pre><code>[System.Array](Get-SelectPropertyArray2 $propsToSelect)
  </code></pre>
  
  <p>When i do a GetType() at initialization, addition to array and return statements the Type is always System.Object, System.Array</p>
  
  <p>However in the calling function it is becomes System.HashTable</p>
  
  <p>Here is an example of using the function:</p>
  
  <pre><code>$propsToSelect = @("Name","Path","PSPath")
  # Get-SelectPropertyArraySet takes a field to return, an alias and an optional code block (to override the default)
  $propsToSelect += Get-SelectPropertyArraySet "." "Asp_AppAllowClientDebug" {
                      (get-webconfigurationProperty -filter /system.webServer/asp -Name AppAllowClientDebug -PSPath $PSPath).Value }
  $propsToSelect += Get-SelectPropertyArraySet "." "Asp_AppAllowDebugging" {
                      (get-webconfigurationProperty -filter /system.webServer/asp -Name AppAllowDebugging -PSPath $PSPath).Value }
  
  $props = (Get-SelectPropertyArray2 $propsToSelect)
  # the following line is the one that fails
  $config = Get-Item $PSPath | select -Property $props
  </code></pre>
  
  <p><strong>the following line is the one that fails</strong> unless i rebuild the array as shown above.</p>
  
  <pre><code>$config = Get-Item $PSPath | select -Property $props
  </code></pre>
  
  <p>When i write out the types, i get the following results:</p>
  
  <pre><code>PS C:\scripts\ps\bits&gt; $p = Get-SelectPropertyArray2 $set
  init:
  
  IsPublic IsSerial Name                                     BaseType
  -------- -------- ----                                     --------
  True     True     Object[]                                 System.Array
  
  
  Inc Alias:
  
  IsPublic IsSerial Name                                     BaseType
  -------- -------- ----                                     --------
  True     True     Object[]                                 System.Array
  
  
  return:
  
  IsPublic IsSerial Name                                     BaseType
  -------- -------- ----                                     --------
  True     True     Object[]                                 System.Array
  
  
  PS C:\scripts\ps\bits&gt; $p.GetType()
  
  IsPublic IsSerial Name                                     BaseType
  -------- -------- ----                                     --------
  True     True     Hashtable                                System.Object
  </code></pre>
  
  <p>As you can see the last one is quite different, if i then use this on my select statement it will fail with the exception shown previously.</p>
  
  <p>Here are the functions code:</p>
  
  <pre><code>&lt;#
      .SYNOPSIS
      Generates a PSObject with a Field/Alias/Expression set for use with the Get-SelectPropertyArray2 function.
      .DESCRIPTION
      Generates a PSObject with a Field/Alias/Expression Set for use with the Get-SelectPropertyArray2 function.
  
      The Alias property is optional
  
      .EXAMPLE
      Get-SelectPropertyArraySet "Name"
  
      .EXAMPLE 
      Get-SelectPropertyArraySet "AccessFlags" "Access Flags"
  
      .EXAMPLE 
      Get-SelectPropertyArraySet "AccessFlags" "Access Flags"
  
      .EXAMPLE
      $propsToSelect = @(
                          (Get-SelectPropertyArraySet "Name"),
                          (Get-SelectPropertyArraySet "AccessFlags" "Access Flags"),
                          (Get-SelectPropertyArraySet "AuthAnonymous" "Auth Anonymous")
                          )
  
      Get-SelectPropertyArray2  $propsToSelect
  
      .PARAMETER Field
      [string] Name of the field to select
      .PARAMETER Alias
      [string] Alias Name of the field to select
      .PARAMETER Expression
      [ScriptBlock] Script block to use for capturing the data, allows for custom field definitions outside standard aliasing.
  
  #&gt;
  function Get-SelectPropertyArraySet 
  {
      [CmdletBinding()]
      param(
          [Parameter(Mandatory=$true)]
          [Alias("f")]
             [string]$Field,
          [Parameter(Mandatory=$false)]
          [Alias("a")]
             [string]$Alias,
          [Parameter(Mandatory=$false)]
          [Alias("e")]
             [ScriptBlock]$Expression
      )
      #Write-Host "Building Property Set for $field, $alias"# with $Expression"
      new-object PSObject -Property @{Field=$field; Alias=$alias; Expression=$expression}
  }
  </code></pre>
  
  <p>And the second function (the lines to write out the data types are included but commented out):</p>
  
  <pre><code>&lt;#
      .SYNOPSIS
      Generates an array of script blocks which can be passed to a select statement. Aliasing the field name.
      .DESCRIPTION
      Generates an array of script blocks which can be passed to a select statement. Aliasing the field name.
  
      The input is an PSObject with a Field and Alias property
  
      For Example:
      Field:    Alias:       
      -----------  ------------
      Name         Name
      MyField      MyField Alias
  
      A helper function Get-SelectPropertyArraySet can be used to create this PSObject.
  
      .EXAMPLE
      $propsToSelect = @(
                          (Get-SelectPropertyArraySet "Name"),
                          (Get-SelectPropertyArraySet "AccessFlags" "Access Flags"),
                          (Get-SelectPropertyArraySet "AuthAnonymous" "Auth Anonymous")
                          )
      $propsToSelect | Get-SelectPropertyArray2
  
      .EXAMPLE
      $propsToSelect = @(
                          (Get-SelectPropertyArraySet "Name"),
                          (Get-SelectPropertyArraySet "AccessFlags" "Access Flags"),
                          (Get-SelectPropertyArraySet "AuthAnonymous" "Auth Anonymous")
                          )
  
      Get-SelectPropertyArray2  $propsToSelect
      .EXAMPLE
      $propsToSelect = @(
                          (new-object PSObject -Property @{Field="Name"}),
                          (new-object PSObject -Property @{Field="AccessFlags"; Alias="Access Flags"}),
                          (new-object PSObject -Property @{Field="AuthAnonymous"; Alias="Auth Anonymous"})
                          )
  
      Get-SelectPropertyArray2  $propsToSelect
  
  
  
  
      .PARAMETER PropertiesToSelect
      [PSObject] array containing the Field/Alias pair to use
  
  #&gt;
  function Get-SelectPropertyArray2
  {
      [CmdletBinding()]
      param(
          [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
          [Alias("Prop")]
             [PSObject]$PropertiesToSelect
      )
      begin {
          #Initialize property-array for Select-Object
          $PropArray = @()
          #write-host "init"
          #write-host init: 
          #$PropArray.GetType() | out-host
  
      }
      process {
  
          #create script block for each field in the input array/pipeline
          #write-host "start"
          #$PropertiesToSelect | select Field,Alias
          foreach ($PropertySet in $PropertiesToSelect)
          {
              $sb = $null
              if ($PropertySet.GetType().Name -eq "String")
              {
                  #Write-Host string found
                  $fieldName = $PropertySet
                  $fieldAlias = $null
              }
              else
              {
                  #Write-Host object found
                  $fieldName = $PropertySet.Field
                  $fieldAlias = $PropertySet.Alias  
                  #use provided expression if present and valid type
                  if ($PropertySet.Expression)
                  {
                      #write-host "Expression Found"
                      #$Propertyset.Expression.GetType().Name
                      switch ($Propertyset.Expression.GetType().Name)
                      {
                          "ScriptBlock"
                          {
                              #Write-Host "Expression is [ScriptBlock]"
                              $sb = $PropertySet.Expression
                          }
                          "String"
                          {
                              #Write-Host "Expression is [String], converting to [ScriptBlock]"
  
                              $sb = [Scriptblock]::Create($PropertySet.Expression)
                          }
                      }
                  }
              }
  
  
  
              if (! ($sb)) { &lt;#write-host "No SB, using default";#&gt; $sb = [Scriptblock]::Create("`$_.`"$fieldName`"") }
  
              #"Mapping Field: {0} --&gt; {1}" -f $fieldName,$FieldAlias |Write-Host
              if ($FieldAlias)
              {
                  #write-host Inc Alias: 
                  #$PropArray.GetType() | out-host
                  $PropArray += @{n=[string]$fieldAlias;e=($sb)}
              }
              else #singleton - no alias
              {
                  #write-host Inc Field: 
                  #$PropArray.GetType()  |out-host
                  $PropArray += @{n=[string]$fieldName;e=($sb)}
              }
          }
  
          # return the script block array
          #Write-Host "end"
          #write-host "&lt;--$PropertiesToSelect"
  
  
      }
      end {
          #write-host "return:"
          #write-host return: 
          #$PropArray.GetType() |out-host
  
  
  
          return $PropArray
      }
  
  }
  </code></pre>