如何将命名参数传递给Powershell中的另一个脚本

时间:2019-10-22 15:02:35

标签: powershell

我想在不知道命名参数的情况下将所有参数从一个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-commandinvoke-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

有什么明智的方法可以做我想做的事吗?

2 个答案:

答案 0 :(得分:1)

摘录自About Splatting Syntax

  

为位置参数提供参数值,其中   参数名称不是必需的,请使用 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实例来执行我​​需要的操作感觉很丑。

也许有一个更干净的版本。