Thanks to the PowerShell expression mode, PowerShell has some nice ways to de-serialize objects, like:
- the
Invoke-Expressioncmdlet - the
Invoke-Commandcmdlet - 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...