如何通过Start-Process向PowerShell脚本传递HashTable参数?
这是跨PowerShell进程传递复杂对象的经典坑!因为Start-Process启动的是完全独立的新进程,参数只能以字符串形式传递——直接传HashTable的话,PowerShell会把它转成类似System.Collections.Hashtable的字符串,根本不是你要的内容。下面给你几个实战验证过的解决办法,按场景选就行:
方法1:JSON序列化/反序列化(最常用)
把HashTable转成JSON字符串传递,新进程再把JSON转回HashTable,简单直观,适合大多数场景。
Caller.ps1 代码:
# 定义你的HashTable参数 $CitrixFarm = @{ Name = "ProdFarm" Servers = @("CTX01", "CTX02") Port = 1494 } # 转成压缩格式的JSON字符串,避免换行/空格导致的参数解析问题 $citrixFarmJson = $CitrixFarm | ConvertTo-Json -Compress # 启动高权限PowerShell会话,传递JSON参数(注意引号转义) Start-Process powershell.exe -Verb RunAs -ArgumentList "-File", "C:\Path\To\MyScript.ps1", "-CitrixFarmJson", "`"$citrixFarmJson`""
MyScript.ps1 代码:
param( [string]$CitrixFarmJson ) # PowerShell 7+ 直接用-AsHashtable转回HashTable $CitrixFarm = $CitrixFarmJson | ConvertFrom-Json -AsHashtable # 如果是PowerShell 5.1及以下版本,用这个兼容写法: # $CitrixFarm = $CitrixFarmJson | ConvertFrom-Json | Select-Object -ExpandProperty PSObject.Properties | ForEach-Object { # $ht = @{} # } { # $ht[$_.Name] = $_.Value # } { # $ht # } # 现在就能正常使用HashTable参数了 Write-Host "Farm Name: $($CitrixFarm.Name)" Write-Host "Servers: $($CitrixFarm.Servers -join ', ')"
方法2:Base64编码序列化(避免特殊字符问题)
如果HashTable里包含引号、换行等特殊字符,JSON可能会出现解析错误,这时候用PowerShell原生的CLIXML序列化+Base64编码更稳妥。
Caller.ps1 代码:
$CitrixFarm = @{ Name = "ProdFarm" Servers = @("CTX01", "CTX02") Port = 1494 } # 序列化对象为CLIXML格式,再转成Base64字符串 $serialized = [System.Management.Automation.PSSerializer]::Serialize($CitrixFarm) $encoded = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($serialized)) # 传递Base64编码后的参数 Start-Process powershell.exe -Verb RunAs -ArgumentList "-File", "C:\Path\To\MyScript.ps1", "-CitrixFarmEncoded", "`"$encoded`""
MyScript.ps1 代码:
param( [string]$CitrixFarmEncoded ) # 解码Base64并反序列化为HashTable $decoded = [System.Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($CitrixFarmEncoded)) $CitrixFarm = [System.Management.Automation.PSSerializer]::Deserialize($decoded) # 使用参数示例 Write-Host "Farm Port: $($CitrixFarm.Port)"
方法3:临时文件传递(适合超大对象)
如果HashTable包含大量数据(比如几百条服务器记录),传递字符串可能会触发命令行长度限制,这时候可以把对象写到临时文件,让新进程读取文件内容。
Caller.ps1 代码:
$CitrixFarm = @{ Name = "ProdFarm" Servers = @("CTX01", "CTX02", "CTX03", "CTX04") Port = 1494 Settings = @{ Timeout = 300 EnableSSL = $true } } # 创建临时JSON文件 $tempFile = [System.IO.Path]::GetTempFileName() + ".json" $CitrixFarm | ConvertTo-Json -Depth 10 | Out-File -FilePath $tempFile -Encoding utf8 # 传递临时文件路径 Start-Process powershell.exe -Verb RunAs -ArgumentList "-File", "C:\Path\To\MyScript.ps1", "-CitrixFarmTempFile", "`"$tempFile`"" # 可选:如果不需要保留临时文件,可以延迟删除(确保新进程已读取) # Start-Sleep -Seconds 5 # Remove-Item $tempFile -Force
MyScript.ps1 代码:
param( [string]$CitrixFarmTempFile ) # 读取临时文件并转回HashTable $CitrixFarm = Get-Content $CitrixFarmTempFile -Raw | ConvertFrom-Json -AsHashtable # 处理完成后删除临时文件 Remove-Item $CitrixFarmTempFile -Force # 使用参数示例 Write-Host "Full Farm Settings:`n$($CitrixFarm | Out-String)"
内容的提问来源于stack exchange,提问作者DarkLite1
相关产品推荐
相关产品推荐

