param
(
[Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$True)]
[securestring]
$securityKey
)
powershell.exe -File $PSCommandPath -thisAppDomain @PSBoundParameters
此代码引发以下错误:
无法处理参数转换 参数“ securityKey”。无法将类型为“ System.String”的“ System.Security.SecureString”值转换为类型为“ System.Security.SecureString”
如果我检查securityKey
的类型,则它是一个在开始前的SecureString。我认为它出于某种原因要序列化。我该如何预防?
这个用例可能看起来很奇怪,所以我会提供一些上下文。我需要确保在管道传递到此脚本时加载了特定版本的程序集。我正在使用thisAppDomain
参数在新的应用程序域中重新启动以尝试完成此操作。较大的示例:
.\FirstScript.ps1 | .\SecondScript.ps1
安全字符串已按预期进行管道传递,但在重新启动时会转换为字符串。这是我重新启动的方式:
if(-not $thisAppDomain)
{
Write-Host "Invoking script in a new app domain"
powershell.exe -File $PSCommandPath -thisAppDomain @PSBoundParameters
return;
}
答案 0 :(得分:1)
可执行文件(甚至powershell.exe
)上的扩展参数仅被转换为字符串。您可以通过运行以下命令查看结果:
$splat = @{ Test = 'something'; Secret = [securestring]::new() }
cmd.exe /c echo @splat
# returns
# -Test:something -Secret:System.Security.SecureString
通过使用SecureString
,可以在使用Start-Job
的同时在另一个进程中运行某些内容
$mySecureString = Read-Host -AsSecureString
$job = Start-Job {
& $using:PSCommandPath -thisAppDomain $using:mySecureString
}
$job | Receive-Job -Wait
注意:using
范围必须用于父会话中的变量。此外,由于进程不共享内存,因此变量仍将被序列化,但是安全字符串将被正确序列化。
答案 1 :(得分:1)
如果您使用-File
调用PowerShell的CLI,则所有参数都将始终转换为 strings ,因此您的安全字符串将不起作用(它将转换为具有 literal 内容System.Security.SecureString
的常规字符串。
为了(主要)保留参数类型,您必须传递 script块 ,这会导致PowerShell以保留类型的方式自动序列化和反序列化参数< sup> [1] ,它可以正确保留[securestring]
个实例,但是请注意,该技术仅在从 PowerShell(太)调用时起作用:
if (-not $thisAppDomain)
{
Write-Host "Invoking script in a new app domain"
powershell -Command {
$script, $splat = $Args # parse the args array into distinct variables
. $script -thisAppDomain @splat # call the script with splatting
} -args $PSCommandPath, $PSBoundParameters
return
}
请注意,必须在脚本块中引用的调用者上下文中的值(将在 new 会话中执行)如何通过参数作为参数传递给 -args <arg-array>
-请参阅Get-Help about_powershell.exe
或运行powershell -?
以获得更简洁的帮助。
注意:正如 Patrick Meinecke所指出的那样,上述方法在幕后使用带有Base64编码字符串的转换后的命令行,可能会由于超出最大值而失败。命令行长度,在Windows 10中为32,768个字符(请参见CreateProcess
WinAPI function)。
也就是说,除非您传递异常大的脚本块和/或数百个参数,否则您不太可能会遇到此限制。
[1]例如,在PowerShell远程处理和后台作业中也使用了相同类型的序列化。请注意,不仅可以忠实地反序列化一组固定的类型,而且PowerShell会尽力使用具有相同属性的自定义对象来模拟其他类型。