I have a workflow that is pretty picky with the PSCustomObjects it receives. I often use Select-Object
to get the properties from the objects I want to keep and sometimes I need to convert some of the values to more usable formats. The easiest way to do this is to use the @{Name='Name'; Expression = {'Expression'}}
technique.
BUT, that technique messes up the PSCustomObject in a way that blocks my further workflow.
The issue can be reproduced like this:
$object = [pscustomobject]@{
Text = "This is a string"
}
In the output below, the Definition for string is 'string Text=This is a string'
$object | Select-Object * | Get-Member
<# Outputs
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Text NoteProperty string Text=This is a string
#>
When adding a new NoteProperty with the Select-Object technique, the Definition is 'System.String Text2=This is a string'
This is what makes my next cmdlet throw.
$WhatHappensToText = $object | Select-Object @{Name='Text'; Expression={$_.Text}}
$WhatHappensToText | Get-Member
<# Outputs
TypeName: Selected.System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Text NoteProperty System.String Text=This is a string
#>
When stripping the surplus like below, Definition is back to 'string Text2=This is a string'
Exporting to Clixml and re-importing does the same
$WhatHappensToText | ConvertTo-Json | ConvertFrom-Json | Get-Member
<# Outputs
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Text NoteProperty string Text=This is a string
#>
If I add the new NoteProperty like this, Definition is 'string Text2=This is a string' as I like it
$object2 = $object | Select-Object *
$object2 | foreach-object {$_ | Add-Member -MemberType NoteProperty -Name Text2 -Value $_.Text}
$object2 | Get-Member
<# Outputs
TypeName: Selected.System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Text NoteProperty string Text=This is a string
Text2 NoteProperty string Text2=This is a string
#>
I have the following questions:
Why is the @{Name='Name'; Expression = {'Expression'}}
technique adding System.String to the Definition and not string like in the Add-Member scenario?
Is there a way to make the @{Name='Name'; Expression = {'Expression'}}
technique add a string and not a System.String?