功能参数位置突然表现得很奇怪

Function Parameter Position suddenly acting weird

提问人:GaryAtlan82 提问时间:8/8/2023 最后编辑:mklement0GaryAtlan82 更新时间:8/8/2023 访问量:45

问:

法典:

这个例子说明了我的意思:

Function test{
    param(
    [parameter(Position = 0, ValueFromPipeline)]
    [string]$Param0,
    [parameter(Position = 1)]
    [ArgumentCompletions("Param1_Opt1", "Param1_Opt2")]
    [Array]$Param1 = ('Param1_Opt3', 'Param1_Opt4'),
    [switch]$NoHeader
    )
    "This is $Param0"
    "Header :$Param1"
}

我的问题:

很长一段时间以来,我在编写函数时一直依赖我所有函数中的参数位置,突然间它停止了我使用它们的方式。上面的函数演示了这个问题。test

如果参数具有参数属性,并且还具有该属性。当它在管道中使用时。具有属性的下一个参数将占据其位置。这也意味着接下来的参数,例如 / 得到建议。Position = 0ValueFromPipelinePositionArgumenCompletions"Param1_Opt1""Param1_Opt2"

但我根本没有这种行为。

Test "This is For Parameter Zero" "This is For Parameter One"

---- Ouput -----
This is For Parameter Zero
This is For Parameter One

上面的工作符合预期,第一个字符串被正确分配给,第二个字符串被正确地分配给,进一步的更多参数建议有效,但以下失败并出现错误,管道字符串被分配给。此外,参数完成不起作用:Param0Param1Param1Param1Param1

"This is For Parameter Zero" | Test "This is For Parameter One"
---- Error ----
test: The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
--- OutPut ----
This is For Parameter One
Header :Param1_Opt0 Param1_Opt0

期望输出:

Test "This is For Parameter Zero" "This is For Parameter One"

---- Ouput -----
This is For Parameter Zero
This is For Parameter One

以上是我在正常使用中所期望的,以及以下关于使用管道和参数建议工作时的内容:Param1

"This is For Parameter Zero" | Test "This is For Parameter One"

---- Ouput -----
This is For Parameter Zero
This is For Parameter One
PowerShell 参数传递 管道 位置参数

评论

2赞 Santiago Squarzon 8/8/2023
你想做的事情是正常手段根本不可能做到的。其中一个参数需要命名为 not positional。除非你想探索动态参数和其他可怕的东西。

答:

5赞 mklement0 8/8/2023 #1

圣地亚哥在评论中提供了关键的指针,但让我把它说出来:

在基于管道的调用中,需要使用命名参数绑定到:-Param1

# Note the required use of -Param1
"This is For Parameter Zero" | Test -Param1 "This is For Parameter One"

这是必需的原因是参数绑定的顺序

  • 在开始执行命令之前,首先绑定参数提供的输入。

  • 只有在稍后管道输入处理开始时,才会对每个管道输入对象执行参数绑定。

  • 至于为什么 PowerShell 必须以这种方式绑定参数:

    • 根据设计,传递给命令的参数是预先评估的,评估结果在命令开始执行之前与目标参数绑定一次

    • 管道输入通常是事先不知道的,因为它仅在执行提供输入的命令时生成。

    • 此外,输入提供命令发出的对象的数据类型通常未知,并且命令可以自由地发出不同类型的对象,因此每个发出的对象可能以不同的方式绑定到接收命令的参数。

    • 简而言之:没有办法预先确定管道输入将如何绑定到参数,因此必须将其推迟到运行时,并且必须为每个输入对象单独执行。

因此:

  • "This is For Parameter Zero" | Test "This is For Parameter One"首先单独绑定参数,而不考虑潜在的管道输入,并且,鉴于它是第一个位置参数,它绑定到参数"This is For Parameter One"-Param0

  • 然后,当管道输入处理开始时,PowerShell 会尝试将管道对象绑定到尚未绑定的参数,并且由于函数的唯一管道绑定参数 已绑定,因此参数绑定失败,从而导致你看到的错误。"This is For Parameter Zero"-Param0

    • 按参数名称绑定参数可避免此问题。-Param1

评论

0赞 GaryAtlan82 8/8/2023
我可能要疯了,我查看了我的一些模块的源代码,果然它们具有相同的设计,但我以前从未以这种方式使用过这些命令。这都是我这边的间接假设。感谢您的详细澄清。我不会忘记这个惨痛的教训。
0赞 mklement0 8/8/2023
很高兴听到解释有所帮助,@GaryAtlan82 - 期望它按照您想要的方式工作是很诱人的。