【问题标题】:how to use hashtable to pass parameters to a powershell cmd that uses double dashes before the parameters如何使用哈希表将参数传递给在参数前使用双破折号的powershell cmd
【发布时间】:2022-01-30 20:06:34
【问题描述】:

我正在编写一个使用控制台应用程序中的 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

【问题讨论】:

  • 请编辑您的问题以显示您当前的脚本
  • 如果它“接受带有双破折号的参数”,它就不可能是一个 cmdlet,它必须是一个常规的可执行程序。
  • @SantiagoSquarzon 已编辑。请看一下
  • 如果您正在运行带有哈希表的二进制 splatting 可能无法正常工作,您需要改为 splat 一个数组。
  • Hashtable splatting 使用具有 double 或 sinlge dash 的 cmdlet 可以正常工作,但您的可能不是 cmdlet,而是我之前所说的 Tomalak 的二进制文件

标签: powershell azure-powershell


【解决方案1】:

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

它可能会起作用,但绝对不是一个好主意,参数名称带有破折号,因为这将导致函数/cmdlet 无法使用 named parameters使用时,PowerShell 会按位置绑定参数! (感谢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

至于外部程序,cmets 中的linked answer 很好地解释了您可以使用包装函数和使用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

【讨论】:

  • 顺便说一句,另一个不一致的地方是,对于外部程序,带有键 '-foo' 的散列表飞溅确实足以在命令行上创建 --foo。
【解决方案2】:

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

  • 相比之下,基于 hashtable 的 splatting 通常仅在调用 PowerShell 命令时才有用(虽然它在技术上也适用于外部程序,但生成的参数格式(例如 @987654322 @ 或 -foo:"bar none") 是不寻常的,很少被外部程序理解)

请注意,参数名称和值必须作为单独数组元素传递,并且表示参数名称的元素必须包括-或--前缀;例如,连续的数组元素 '--sqlConnectionStrings'(名称)和
'Data Source=Server1'(值)。

然后PowerShell构造一个命令行来在后台调用外部程序,用空格分隔数组元素并根据需要用嵌入空格的元素双引号;上面的例子变成如下:
--sqlConnectionStrings "Data Source=Server1"

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

# 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
  }
}

【讨论】:

    猜你喜欢
    • 2019-11-07
    • 2022-01-05
    • 2014-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-11
    • 2012-10-07
    相关资源
    最近更新 更多