ConvertFrom-Expression.ps1
<#PSScriptInfo
.VERSION 1.0.3 .GUID 346b6ee5-a5f4-498f-b852-0f129bf6ec21 .AUTHOR Ronald Bode (iRon) .DESCRIPTION This cmdlet is deprecated, a replacement might be found in the ObjectGraphTools module. .COMPANYNAME .COPYRIGHT .TAGS Desrialize Invoke Expression ScriptBlock .LICENSEURI https://github.com/iRon7/ConvertFrom-Expression/LICENSE.txt .PROJECTURI https://github.com/iRon7/ObjectGraphTools .ICONURI https://raw.githubusercontent.com/iRon7/ConvertFrom-Expression/master/ConvertFrom-Expression.png .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES .PRIVATEDATA #> using namespace System.Management.Automation.Language function Show-AST { [CmdletBinding()]Param ( [Parameter(ParameterSetName = 'Expression', Position = 0, Mandatory = $True, ValueFromPipeLine = $True)]$Expression, [Parameter(ParameterSetName = 'FilePath', Position = 1, Mandatory = $True)][String[]]$FilePath, [Switch]$NoEnumerate, [Switch]$NoNewScope ) Begin { function Get-AST([Ast]$AST, [Int]$Depth = 0) { (' ' * $Depth) + 'type: ' + $AST.GetType().Name if ($AST -is [TypeConstraintAst]) { # Write-Host 'TYPE' $AST.TypeName } elseif ($AST -is [StringConstantExpressionAst]) { # Write-Host '***' $AST.Value $AST.SafeGetValue() $AST.Value } elseif ($AST -is [ScriptBlockAst]) { # Write-Host 'ScriptBlock' } elseif ($AST -is [HashtableAst]) { $hashTable = @{} foreach ($keyValuePair in $AST.KeyValuePairs) { (' ' * $Depth) + 'Key: ' + $keyValuePair.Item1 Get-AST $keyValuePair.Item2 ($Depth + 1) } $hashTable } foreach ($property in $AST.PSObject.Properties) { # Skip the Parent node, it's not useful here if ($property.Name -eq 'Parent') { continue } # Recursively add only Ast nodes. foreach ($item in @($property.Value).where{ $_ -is [Ast] }) { (' ' * $Depth) + 'Name: ' + $Property.Name Get-AST $item ($Depth + 1) } } } } Process { # If ($Expression) {$Expression | ForEach-Object {Deserialize $_}} # ElseIf ($FilePath) {$FilePath | ForEach-Object {Deserialize (Get-Content -Raw $_)}} } End { Get-AST ([Parser]::ParseInput($Expression, [ref]$null, [ref]$null)) } } Function ConvertFrom-Expression { <# .SYNOPSIS Deserializes a object. .DESCRIPTION The ConvertoFrom-Expression cmdlet convert an object from a formatted expression string, command scriptblock or file. .INPUTS Sting or ScriptBlock. Each String or ScriptBlock provided through the pipeline will evaluted and converted to an PowerShell object. .OUTPUTS Any. One or more PowerShell objects. .PARAMETER Expression Specifies the expression or command to evaluate. .PARAMETER FilePath Specifies the path to the file containing an expression or command to be evaluated. .PARAMETER NoEnumerate Indicates that this cmdlet runs the expression in the current scope. By default, ConvertFrom-Expression runs commands in their own scope. .PARAMETER NoNewScope By default, the ConvertFrom-Expression cmdlet enumerates its output. The NoEnumerate parameter prevents the output enumerating. .EXAMPLE PS C:\>$Expression = ",[PSCustomObject]@{Name = 'Test'; Value = 123}" PS C:\>$Object = ConvertFrom-Expression -NoEnumerate $Expression PS C:\>$Object Name Value ---- ----- Test 123 PS C:\> $Object -is [Array] True .LINK https://www.powershellgallery.com/packages/ConvertTo-Expression #> [CmdletBinding()]Param ( [Parameter(ParameterSetName = 'Expression', Position = 0, Mandatory = $True, ValueFromPipeLine = $True)]$Expression, [Parameter(ParameterSetName = 'FilePath', Position = 1, Mandatory = $True)][String[]]$FilePath, [Switch]$NoEnumerate, [Switch]$NoNewScope ) Begin { $AllowedTypes = # https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_language_modes?view=powershell-7 [Array], [Bool], [byte], [char], [DateTime], [decimal], [double], [float], [Guid], [Hashtable], [int], [Int16], [long], [NullString], [PSCredential], [PSListModifier], [PSObject], [PSPrimitiveDictionary], [PSTypeNameAttribute], [Regex], [SByte], [string], [System.Globalization.CultureInfo], [System.Net.IPAddress], [System.Net.Mail.MailAddress], [System.Numerics.BigInteger], [System.Security.SecureString], [TimeSpan], [UInt16], [UInt32], [UInt64] $TypeAccelerators = [psobject].Assembly.GetType("System.Management.Automation.TypeAccelerators") $TypeAccelerators::Add('TypeAccelerators', $TypeAccelerators) function Get-AST([Ast]$AST) { if ($AST -is [ScriptBlockAst]) { If ($Null -ne $AST.BeginBlock) { Get-AST $AST.BeginBlock } If ($Null -ne $AST.ProcessBlock) { Get-AST $AST.ProcessBlock } If ($Null -ne $AST.EndBlock) { Get-AST $AST.EndBlock } } elseif ($AST -is [NamedBlockAst]) { @($AST.Statements).Foreach{ Get-AST $_ } } elseif ($AST -is [PipelineAst]) { @($AST.PipelineElements).Foreach{ Get-AST $_ } } elseif ($AST -is [CommandExpressionAst]) { If ($Null -ne $AST.Expression) { if ($AST.Expression -is [ConstantExpressionAst]) { $AST.Expression.Value } elseif ($AST.Expression -is [StringConstantExpressionAst]) { $AST.Expression.SafeGetValue() } elseif ($AST.Expression -is [ExpandableStringExpressionAst]) { $AST.Expression.Value } elseif ($AST.Expression -is [ConvertExpressionAst]) { $AST.Expression.Type.TypeName If ($AllowedTypes.Contains($AST.Expression.Type)) { Write-Host $AST.Expression.Type $t = [System.Type]::GetType('System.Int32') [Convert]::ChangeType(($AST.Expression.Child), $t) } } elseif ($AST.Expression -is [HashtableAst]) { $hashTable = @{} foreach ($keyValuePair in $AST.Expression.KeyValuePairs) { $hashTable[$keyValuePair.Item1.Value] = Get-AST $keyValuePair.Item2 } $hashTable } else { Write-Host 'Unknown AST expression type:' $AST.Expression.GetType().Name } } } } } Process { # If ($Expression) {$Expression | ForEach-Object {Deserialize $_}} # ElseIf ($FilePath) {$FilePath | ForEach-Object {Deserialize (Get-Content -Raw $_)}} } End { Get-AST ([Parser]::ParseInput($Expression, [ref]$null, [ref]$null)) } }; Set-Alias cfex ConvertFrom-Expression $Expression = @' @{ RB = 'Ronald' JB = '$Jose' DB = [String]'Dennis' SB = 25 } '@ Set-StrictMode -Off # Show-AST $Expression cfex $Expression |