如何使用哈希表将参数传递给在参数前使用双破折号的 powershell cmd

how to use hashtable to pass parameters to a powershell cmd that uses double dashes before the parameters

我正在编写一个脚本,该脚本使用来自控制台应用程序的 cmdlet,我们将该 cmdlet 称为 cmdA。我无法控制 cmdA 的实施。 cmdA 采用双破折号参数 (cmdA --param1 value1 --param2 value2 --param3 value3 --param4 value4 --param5 value5)

现在param2、param3、param4和param5是可选的。我的脚本的用户可能会也可能不会为这些可选参数提供值。在脚本中,我使用用户提供值的参数形成了一个哈希表。我们称它为 paramHashtable。

我正在执行 cmdA @paramHashtable 但这不起作用。我认为它必须用双破折号做一些事情,因为这种方法适用于采用单破折号

参数的 cmd

将参数传递给 cmdA 的有效方法是什么(一种低效的方法是使用许多 if 块来检查提供了哪些值并相应地进行调用)

已编辑*

这就是我创建哈希表的方式:-

$optionalParameters = @{}
$optionalParameters = ParameterSelection ${OutputFolder} ${PerfQueryIntervalInSec} ${StaticQueryIntervalInSec} ${NumberOfIterations}
$requiredParameters = @{"sqlConnectionStrings " = "$SqlConnectionStrings"}
$parameters = $requiredParameters + $optionalParameters

function ParameterSelection ([string] $outputFolder, [string] $perfQueryIntervalInSec, [string] $staticQueryIntervalInSec, [string] $numberOfIterations)
{
    $parametersList = @{}
    if($outputFolder -ne "")
    {
        $parametersList["outputFolder "] = $outputFolder    
    }
    if($perfQueryIntervalInSec -ne "")
    {
        $parametersList["perfQueryIntervalInSec "] = $perfQueryIntervalInSec 
    }
    if($staticQueryIntervalInSec -ne "")
    {
        $parametersList["staticQueryIntervalInSec "] = $staticQueryIntervalInSec
    }
    if($numberOfIterations -ne "")
    {
        $parametersList["numberOfIterations "] = $numberOfIterations 
    }

    return $parametersList
}

我是这样称呼它的:-

& $ExePath actionName @parameters

$ExePath中有要执行的程序的路径 actionName 采用如下参数:-

actionName --sqlConnectionStrings "Data Source=Server1" --outputFolder C:\Output

splatting with hash table 可以在其参数有破折号的 cmdlet/函数上工作吗?

它可能有效但绝对不是一个好主意参数名称带有破折号,因为这将导致一个函数/ cmdlet,其中 named parameters cannot be used, PowerShell binds the arguments positionally! (thanks mklement0 用于指出这一点):

function Test-Splatting {
    param(${-param1}, ${-param2})
    "${-param1} ${-param2}"
}

$param = @{ '--param1' = 'hello'; '--param2' = 'world' }
Test-Splatting @param # => hello world

使用上述相同功能之前提到的示例:

# --param1 is bound positionally and not interpreted as a parameter:
Test-Splatting --param1 hello # => --param1 hello

至于外部程序, in comments explains very well the approach you could take using a wrapper function and the use of the automatic variable $args:

function myfunc {
    $binaryPath = 'path/to/file.exe'
    & $binaryPath actionName $args
    # or @args we can't be sure until testing
}

myfunc --sqlConnectionStrings "Data Source=Server1" --outputFolder C:\Output

如评论中所述,因为您正在调用外部程序,您应该使用基于数组splatting 或直接数组 以传递以编程方式构造的参数。

  • 相比之下,基于 hashtable 的展开通常只在调用 PowerShell 命令时有用(虽然它在技术上也适用于外部程序,生成的参数格式(例如 -foo:bar-foo:"bar none")不常见,很少有外部程序可以理解)

请注意,参数名称和值必须作为单独的数组元素和表示参数的元素names 必须 include - or -- prefix;例如,连续的数组元素 '--sqlConnectionStrings'(名字)和
'Data Source=Server1'(值)。

PowerShell然后构造一个命令行用于在后台调用外部程序,space-separating数组元素和double-quoting按需嵌入空格的元素;上面的例子变成了下面的:
--sqlConnectionStrings "Data Source=Server1"

请注意,由目标程序以识别参数 name-value 对的方式解析作为其命令行的单个字符串。

# Get the array of *optional* parameter names and values from your helper function.
$optionalParameters = ParameterSelection ${OutputFolder} ${PerfQueryIntervalInSec} ${StaticQueryIntervalInSec} ${NumberOfIterations}

# Declare the *required* parameter(s) as an array.
$requiredParameters = '--sqlConnectionStrings', $SqlConnectionStrings

# Pass the arrays as-is to the external program.
# (Empty arrays are effectively ignored.)
& $ExePath actionName $requiredParameters $optionalParmeters

你的ParameterSelection函数可以简化如下:

function ParameterSelection ([string] $outputFolder, [string] $perfQueryIntervalInSec, [string] $staticQueryIntervalInSec, [string] $numberOfIterations)
{
  # Loop over all bound parameters.
  $PSBoundParameters.GetEnumerator() | ForEach-Object {
    # Emit the parameter name prefixed with '--' and the value.
    # PowerShell automatically collects the output strings in an array
    # when you assign a call to this function to a variable.
    '--' + $_.Key
    $_.Value
  }
}