我想在不知道命名参数的情况下将所有参数从一个Powershell脚本传递到另一个脚本。该其他脚本无法控制,我无法预测所需的所有参数。
示例包装:wrapper.ps1
Set-StrictMode -v 2
$ErrorActionPreference="Stop"
write-host "ArgsIn:" $Args
$mypath= Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
$Cmd, $NewArgs =$Args | foreach { $_ -replace "one",'two' }
$Cmd = $mypath+"\"+$Cmd
write-host "Running:" $Cmd $NewArgs
& $Cmd @NewArgs
exit $LastExitCode
名为脚本的示例:test.ps1
)
Param(
[Parameter(Mandatory=$false)] [string]$BAR,
[Parameter(Mandatory=$false)] [string]$FOO
)
write-host "test: Args:" $Args
write-host "FOO" $FOO
write-host "BAR" $BAR
exit 0
如果我致电test.ps1
,它将按预期工作:
PS C:\Test> .\test.ps1 -foo one -bar three
test: Args:
FOO one
BAR three
但是,如果我通过包装程序尝试使用它,则会在位置上映射参数。
PS C:\Test> .\wrapper.ps1 test.ps1 -foo one
ArgsIn: test.ps1 -foo one
Running: C:\Test\test.ps1 -foo two
test: Args: test.ps1 -foo one
FOO two
BAR -foo
我尝试了各种替代形式来调用脚本(包括invoke-command
和invoke-expression
)。
一种可行的方法是使用
invoke-expression "& `"$Cmd`" $NewArgs"
,但是只要任何参数包含空格,它就会中断:
PS C:\Test> .\wrapper.ps1 test.ps1 -foo "one three"
ArgsIn: test.ps1 -foo one three
Running: C:\Test\test.ps1 -foo two three
test: Args:
FOO two
BAR three
有什么明智的方法可以做我想做的事吗?
答案 0 :(得分:1)
为位置参数提供参数值,其中 参数名称不是必需的,请使用 array 语法。提供 参数名称和值对,请使用哈希表语法。的 喷射值可以出现在参数列表中的任何位置。
换句话说,如果要传递 named 参数,则应将参数作为哈希表(而不是数组)展开。像这样:
[CmdletBinding()] Param (
$Cmd,
[parameter(ValueFromRemainingArguments=$true)]$RemainingArguments
)
Set-StrictMode -v 2
$ErrorActionPreference="Stop"
$Cmd = $PSScriptRoot + '\' + $Cmd
$ArgName = $Null; $NewArgs = @{}
ForEach ($Arg in $RemainingArguments) {
If ($Arg.StartsWith('-')) {$ArgName = $Arg.SubString(1)}
ElseIf ($ArgName) {$NewArgs[$ArgName] = $Arg}
}
# $NewArgs['Foo'] = 'Three test'
write-host "Running:" $Cmd $NewArgs
& $Cmd @NewArgs
结果:
PS C:\> .\wrapper.ps1 test.ps1 -foo 'one three'
Running: C:\...\test.ps1 System.Collections.DictionaryEntry
test: Args:
FOO one three
BAR
答案 1 :(得分:0)
我实际上偶然发现了一些可行的方法:
& powershell.exe -file $Cmd @NewArgs
但是调用第二个powershell实例来执行我需要的操作感觉很丑。
也许有一个更干净的版本。