ConvertTo-CustomObject function as a wrapper for Select-Object

In yesterday’s post I introduced a custom advanced function for changing property names on objects. I also showed you how to use Select-Object to do the same. Because the Select-Object cmdlet is probably more robust than my little function I decided to try and rewrite the function to use Select-Object under the hood.

Select-Object accepts an array of hashtable objects with two key/value pairs:

  • N is for the name of the property
  • E is the expression as a script block that need to be run to get the value

In order to use this functionality we need to figure out a way to generate these objects dynamically using our mapping table. The approach I took was to generate the code as strings and then use Invoke-Expression. Since we only need to do this once and not for every object I added a BEGIN block to my function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
BEGIN {
$Expression = ""
$MappingTable.Keys | ForEach-Object {
$Expression += (
@"
@{
N="$($MappingTable[$_])"
E={`$_.$_}
},
"@
)
}
$Expression = $Expression.Substring(0,$Expression.Length-1)
$SelectObjectParameter = Invoke-Expression $Expression
}

So for each key in the mapping table we generate a name and an expression to run. Eg. using a mapping table like @{ "name" = "AccountName"; "telephone1" = "Phone" }generates the following string:

1
2
3
4
5
6
7
@{
N="Phone"
E={$_.telephone1}
}, @{
N="AccountName"
E={$_.name}
}

That string is exactly what we would feed Select-Object. To get it into actual PowerShell objects we need to feed it to Invoke-Expression. That gives us an array with two separate hashtables each with a N key with a string value and an E key with a script block value.

Once stored in a variable we can use this for each of the objects fed through the pipeline by using it in the PROCESS block of our advanced function:

1
2
3
PROCESS {
$SourceObject | Select-Object -Property $SelectObjectParameter
}

And that is all there is to it. The function works exactly the same as the ‘quick and dirty’ one in the last post. You can find the full function here. Import it to your session and try this example:
Get-Process | ConvertTo-CustomObject -MappingTable @{ "ProcessName" = "Name" }