Thanks to the PowerShell expression mode, PowerShell has some nice ways to de-serialize objects, like:
- the
Invoke-Expression
cmdlet - the
Invoke-Command
cmdlet - the call operator
&
- dot sourcing a PowerShell script file
My general expectation is that the result of an given expression should be the same as using one of above listed de-serialize commands on same serialized version of that expression (for background, see the ConvertTo-Expression answer on the 'Save hash table in PowerShell object notation (PSON)' question).
In other words:
<Expression> <=> Invoke-Command {<Expression>} <=> &([ScriptBlock]::Create('<Expression>'))
<Expression> <=> Invoke-Expression '<Expression>'
Examples:
Get-ChildItem <=> &{Get-ChildItem}
Get-ChildItem <=> Invoke-Command {Get-ChildItem}
Get-ChildItem <=> Invoke-Expression 'Get-ChildItem'
1, 2, 3 <=> &{1, 2, 3}
1, 2, 3 <=> Invoke-Command {1, 2, 3}
1, 2, 3 <=> Invoke-Expression '1, 2, 3'
This indeed appears true for mainly every expression, but due to the fact that PowerShell unrolls (enumerates) the output by default, this definition deviates in the case an expression contain an array with a single item:
,1 <≠> Invoke-Command {,1}
,1 <≠> Invoke-Expression ',1'
,"Test" <≠> Invoke-Command {,"Test"}
,"Test" <≠> Invoke-Expression ',"Test"'
@("Test") <≠> Invoke-Command {@("Test")}
@("Test") <≠> Invoke-Expression '@("Test")'
,@("Test") <≠> Invoke-Command {,@("Test")}
,@("Test") <≠> Invoke-Expression ',@("Test")'
Is there a way to prevent that expressions get unrolled when the are invoked (de-serialized) in anyway?
I am considering to request for a -NoEnumerate
parameter (similar to the Write-Output
cmdlet) for the Invoke-Expression
on the PowerShell GitHub, but that will still leave the issue/question for the call operator and dot sourcing that do not support parameters...