如何防止PowerShell中序列化表达式执行时出现展开(枚举)行为?
关于PowerShell表达式反序列化时防止自动展开的问题
最近我一直在研究PowerShell里表达式的序列化与反序列化逻辑——PowerShell本身提供了不少反序列化对象的方式,比如Invoke-Expression cmdlet、Invoke-Command cmdlet、调用操作符&,还有点源加载脚本文件这些。
我的核心目标是:让原始表达式的执行结果,和把这个表达式序列化后通过上述任意一种反序列化命令执行的结果完全一致。这个思路其实可以参考《将哈希表保存为PowerShell对象表示法(PSON)》里的ConvertTo-Expression方案,简单说就是要满足以下等价关系:
<Expression> <=> Invoke-Command {<Expression>}<Expression> <=> &([ScriptBlock]::Create('<Expression>'))<Expression> <=> Invoke-Expression '<Expression>'
举几个正常情况下成立的例子:
# 获取目录项的表达式等价性 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'
但这里有个棘手的问题:PowerShell默认会自动展开(枚举)输出结果,当表达式是单元素数组的时候,上面的等价关系就不成立了,比如这些情况:
# 单元素数值数组的不等价 ,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")'
现在我想请教的是:有没有什么方法能在调用(反序列化)表达式的时候全局防止这种自动展开的行为?我目前在考虑给PowerShell的GitHub仓库提个功能请求,给Invoke-Expression添加一个类似Write-Output的-NoEnumerate参数,但就算这个参数加上了,也解决不了调用操作符&和点源加载不支持参数的问题,所以想看看有没有更通用的解决方案。
内容的提问来源于stack exchange,提问作者iRon
相关产品推荐
相关产品推荐

