我基本上正在构建自己的并行foreach管道函数,使用runspaces。
我的问题是:我这样调用我的函数:
如何正确将
但是正如你可能已经注意到的那样,PowerShell内置的ForEach-Object和Where-Object在传递给它们的每个ScriptBlock中不需要这样的参数声明。
提前感谢你的回答 fjf2002
编辑:
目标是:我希望函数MyNewForeachFunction的用户能够更加方便 - 他们不需要在自己的脚本块中写一行param($_)。
在MyNewForeachFunction内部,当前通过以下方式调用ScriptBlock:
我的问题是:我这样调用我的函数:
somePipeline | MyNewForeachFunction { scriptBlockHere } | pipelineGoesOn...
如何正确将
$_
参数传递到ScriptBlock中?当ScriptBlock的第一行包含时,它可以正常工作。param($_)
但是正如你可能已经注意到的那样,PowerShell内置的ForEach-Object和Where-Object在传递给它们的每个ScriptBlock中不需要这样的参数声明。
提前感谢你的回答 fjf2002
编辑:
目标是:我希望函数MyNewForeachFunction的用户能够更加方便 - 他们不需要在自己的脚本块中写一行param($_)。
在MyNewForeachFunction内部,当前通过以下方式调用ScriptBlock:
$PSInstance = [powershell]::Create().AddScript($ScriptBlock).AddParameter('_', $_)
$PSInstance.BeginInvoke()
编辑2:
问题是,例如内置函数ForEach-Object
的实现如何实现在其ScriptBlock参数中不需要声明$_
作为参数,并且我能否也使用这个功能?
(如果答案是,ForEach-Object
是一个内置函数并且使用了一些我无法使用的魔法,那么在我看来,PowerShell语言整体上就不合格了)
编辑3:
感谢mklement0,我终于可以构建我的通用foreach循环。以下是代码:
function ForEachParallel {
[CmdletBinding()]
Param(
[Parameter(Mandatory)] [ScriptBlock] $ScriptBlock,
[Parameter(Mandatory=$false)] [int] $PoolSize = 20,
[Parameter(ValueFromPipeline)] $PipelineObject
)
Begin {
$RunspacePool = [runspacefactory]::CreateRunspacePool(1, $poolSize)
$RunspacePool.Open()
$Runspaces = @()
}
Process {
$PSInstance = [powershell]::Create().
AddCommand('Set-Variable').AddParameter('Name', '_').AddParameter('Value', $PipelineObject).
AddCommand('Set-Variable').AddParameter('Name', 'ErrorActionPreference').AddParameter('Value', 'Stop').
AddScript($ScriptBlock)
$PSInstance.RunspacePool = $RunspacePool
$Runspaces += New-Object PSObject -Property @{
Instance = $PSInstance
IAResult = $PSInstance.BeginInvoke()
Argument = $PipelineObject
}
}
End {
while($True) {
$completedRunspaces = @($Runspaces | where {$_.IAResult.IsCompleted})
$completedRunspaces | foreach {
Write-Output $_.Instance.EndInvoke($_.IAResult)
$_.Instance.Dispose()
}
if($completedRunspaces.Count -eq $Runspaces.Count) {
break
}
$Runspaces = @($Runspaces | where { $completedRunspaces -notcontains $_ })
Start-Sleep -Milliseconds 250
}
$RunspacePool.Close()
$RunspacePool.Dispose()
}
}
代码部分来自MathiasR.Jessen,为什么PowerShell工作流在XML文件分析方面比非工作流脚本慢得多
$args[0]
中,或者如果它被视为管道,则在$input
中。 - Maximilian Burszley