[Update:
- The repro code no longer reproduces the problem as of PowerShell 7.5.x: I don't know why.
- Notably,
$v = [psobject] [datetime]::now; $v -is [psobject] now returns $true, as expected.
- (By contrast - as is to be expected - ,
Add-Type 'public struct Foo { public int x; }'; ($v = [Foo]::new()).x = 1; $v.x continues to output 0.)
]
Note: This problem will go away once #7937 is fixed.
For better or worse, if you combine -ExpandProperty with -Property, the properties passed to -Property are added as ETS instance members to the object returned by -ExpandProperty (as NoteProperty members, as with Add-Member). (The way these instance members are added is flawed, as discussed in #7937.)
If the object returned happens to be an instance of a value type (check with [<type>].IsValueType) that isn't also a .NET primitive type (check with [<type>].IsPrimitive) - e.g., [datetime] - these instance members are not added.
This may be related to the fact that wrapping such types in [psobject] seems not to work when saved to a variable: e.g., $v = [psobject] [datetime]::now; $v -is [psobject] returns $false [update: no longer true as of v7.6], even though for a reference-type instance (e.g., [IO.DirectoryInfo]::new('/')) or a .NET primitive type (e.g., 42) it would return $true.
Steps to reproduce
$o = [pscustomobject] @{ one = [datetime]::now; two = [IO.DirectoryInfo]::new('/') }
# OK: reference-type instance [IO.DirectoryInfo] is properly decorated
# with the [datetime] instance as NoteProperty 'one'
$newValue = $o | Select-Object -ExpandProperty two -Property one
$newValue.one | Should -BeOfType System.DateTime
# BROKEN: The non-primitive [datetime] value-type instance is NOT
# decorated with the [IO.DirectoryInfo] instance as property 'two'.
# Note: The Select-Object return value *must be saved in a variable*
# for the bug to surface.
$newValue = $o | Select-Object -ExpandProperty one -Property two
$newValue.two | Should -BeOfType System.IO.DirectoryInfo
Expected behavior
Both tests should succeed.
Actual behavior
The second test fails:
Expected the value to have type [System.IO.DirectoryInfo] or any of its subtypes, but got $null with type $null.
The reason is that the [datetime] instance stored in $newValue did not receive the .two NoteProperty member.
Environment data
PowerShell Core 7.1.0-preview.1
[Update:
$v = [psobject] [datetime]::now; $v -is [psobject]now returns$true, as expected.Add-Type 'public struct Foo { public int x; }'; ($v = [Foo]::new()).x = 1; $v.xcontinues to output0.)]
Note: This problem will go away once #7937 is fixed.
For better or worse, if you combine
-ExpandPropertywith-Property, the properties passed to-Propertyare added as ETS instance members to the object returned by-ExpandProperty(asNotePropertymembers, as withAdd-Member). (The way these instance members are added is flawed, as discussed in #7937.)If the object returned happens to be an instance of a value type (check with
[<type>].IsValueType) that isn't also a .NET primitive type (check with[<type>].IsPrimitive) - e.g.,[datetime]- these instance members are not added.This may be related to the fact that wrapping such types in
[psobject]seems not to work when saved to a variable: e.g.,$v = [psobject] [datetime]::now; $v -is [psobject]returns$false[update: no longer true as of v7.6], even though for a reference-type instance (e.g.,[IO.DirectoryInfo]::new('/')) or a .NET primitive type (e.g.,42) it would return$true.Steps to reproduce
Expected behavior
Both tests should succeed.
Actual behavior
The second test fails:
The reason is that the
[datetime]instance stored in$newValuedid not receive the.twoNoteProperty member.Environment data