如何阻止PowerShell跨版本调用脚本时数组被展开
解决PowerShell 7跨进程调用PowerShell 5返回结构化数组的问题
跨进程调用powershell.exe(即PowerShell 5)时,默认会把脚本输出序列化为控制台格式化后的字符串,而非原始对象,所以你在PowerShell 7中拿到的$files是字符串数组。要传递结构化的对象数组,需要用序列化/反序列化的方式处理,以下是两种解决方案:
方案A:在PowerShell 7调用脚本中还原数组
修改调用命令,让PowerShell 5脚本输出序列化后的结构化数据,再在PowerShell 7中反序列化为对象数组。
方式1:用JSON序列化(推荐,轻量且跨平台)
# 调用PS5脚本并捕获JSON输出 $filesJson = powershell.exe -ExecutionPolicy Bypass -File "$PSScriptRoot\FileInfo.ps1" -Path $FolderToProcess -Title $moduleTitle -GUID $guid | Out-String # 反序列化为对象数组 $files = $filesJson | ConvertFrom-Json
方式2:用PowerShell原生CLIXML序列化(支持更多PowerShell类型)
# 让PS5脚本将对象导出为CLIXML临时文件 powershell.exe -ExecutionPolicy Bypass -Command "& '$PSScriptRoot\FileInfo.ps1' -Path '$FolderToProcess' -Title '$moduleTitle' -GUID '$guid' | Export-Clixml -Path 'temp_object.xml'" # 在PS7中导入还原数组 $files = Import-Clixml -Path 'temp_object.xml' # 清理临时文件 Remove-Item 'temp_object.xml' -Force
方案B:修改被调用的FileInfo.ps1输出结构化数据
直接在PowerShell 5脚本中把对象数组序列化为JSON输出,调用方只需反序列化即可。
修改FileInfo.ps1的末尾代码:
$arr = @() foreach ($file in $finalFiles) { $item = [PSCustomObject]@{ i = $file.i j = $file.j k = $file.k } $arr += $item } # 输出压缩格式的JSON,避免换行导致的解析问题 $arr | ConvertTo-Json -Compress
然后在PowerShell 7的调用脚本中处理:
$filesJson = powershell.exe -ExecutionPolicy Bypass -File "$PSScriptRoot\FileInfo.ps1" -Path $FolderToProcess -Title $moduleTitle -GUID $guid | Out-String $files = $filesJson | ConvertFrom-Json
额外优化:用-Command参数直接管道序列化
如果不想修改FileInfo.ps1,也可以用-Command参数替代-File,直接在调用时添加序列化逻辑:
$files = powershell.exe -ExecutionPolicy Bypass -Command "& '$PSScriptRoot\FileInfo.ps1' -Path '$FolderToProcess' -Title '$moduleTitle' -GUID '$guid' | ConvertTo-Json" | ConvertFrom-Json
注意:如果参数包含空格、引号等特殊字符,需要正确转义;或者使用-EncodedCommand参数对命令进行Base64编码,避免转义问题。
内容的提问来源于stack exchange,提问作者Graham Reynolds
相关产品推荐
相关产品推荐

