我有一个高级功能
function Start-Executable {
[CmdletBinding()]
Param (
[String]$Arg1,
[String[]]$Arg2,
[Parameter(ValueFromPipeline=$true)][String[]]$PipeValue
)
Begin {
# Setup code
}
Process {
# What goes on here?
foreach ($val in $PipeValue) {
# Process val here
}
}
End {
}
}
在我的设置代码中,我需要做一些不同的操作,具体取决于用户是否提供了管道输入。但我不知道如何在我的BEGIN块中判断是否存在管道输入。有什么我可以检查的吗?
我尝试的另一件事是在$PipeValue
循环之前将设置代码放在PROCESS块中,但这不起作用,因为看起来每个管道值都调用一次PROCESS块, $PipeValue
每次都是一个项目的数组。是对的吗?如果为每个值重复调用PROCESS,为什么在PROCESS块中需要另一个循环?
更新
为了澄清,我要做的是在BEGIN中创建一个进程,在PROCESS中输入它并在END中读取输出。为此,我需要将RedirectStandardInput
设置为$true
,如果有管道输入,则不然。
作为解决方法,我可以让用户指定一个额外的参数(如果他们弄错了,事情就行不通)或者我可以在BEGIN中设置一个$first_time
标志,然后创建进程第一次调用PROCESS。如果我在没有创建过程的情况下进入END,我会使用RedirectStandardInput
创建$false
。这比我喜欢的代码重复更多,但如果它是唯一的选择,我可能必须这样做。
答案 0 :(得分:3)
Begin块在管道启动之前运行,因此该代码无法知道管道中的内容。
至于在Process块中需要另一个循环,如果函数需要接受任何$ PipeValue作为管道输入或作为参数传递,则必须具有该循环。如果它只是接受它作为管道数据,那么就没有必要为它提供参数。只需在进程块中使用$ _。
答案 1 :(得分:3)
$MyInvocation.ExpectingInput
如果通过管道输入调用该函数,则返回true,否则返回false。
这在begin
,process
和end
块中有效。它不适用于dynamicparam
in PowerShell 5.1 or lower。
答案 2 :(得分:2)
function Start-Executable {
[CmdletBinding()]
Param (
[String]$Arg1,
[String[]]$Arg2,
[Parameter(ValueFromPipeline=$true, parametersetname="nopipeline")][String[]]$PipeValue
)
Begin {
# Setup code
if($PSCmdlet.ParameterSetName -eq "nopipeline")
{
Write-Host "No pipeline input"
}
else
{
Write-Host "Pipeline input"
}
}
Process {
$PipeValue
}
End {
}
}
这似乎可以解决问题
基本上,参数被分配给参数集
如果使用该参数,则$pscmdlet.ParameterSetName
包含"nopipeline"
如果使用管道,则$pscmdlet.ParameterSetName
包含"__AllParameterSets"
示例输出:
PS H:\> @("a","b","c") | Start-Executable
Pipeline input
a
b
c
PS H:\> Start-Executable -PipeValue @("a","b","c")
No pipeline input
a
b
c
编辑:请注意,这不会告诉您是管道输入。它将告诉您是否使用了命名参数。 换句话说,这种情况发生了:
PS H:\> Start-Executable
Pipeline input