使用ForEach-Object -Parallel时自定义函数无法识别的问题
ForEach-Object -Parallel 无法调用脚本中定义的函数?
环境信息
Name Value ---- ----- PSVersion 7.3.3 PSEdition Core GitCommitId 7.3.3 OS Microsoft Windows 10.0.19044 Platform Win32NT PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…} PSRemotingProtocolVersion 2.3 SerializationVersion 1.1.0.1 WSManStackVersion 3.0
正常执行的代码与结果
在普通ForEach-Object块中调用脚本顶层定义的CustomPrint函数可以正常运行:
function CustomPrint { param($Item) Write-Output $Item.Name } Get-ChildItem "." -Recurse -Filter "*.txt" | ForEach-Object { &CustomPrint -Item $_ }
输出:
test1.txt test2.txt test3.txt
添加-Parallel参数后的错误情况
当使用-Parallel参数后,执行脚本出现函数未识别的错误:
function CustomPrint { param($Item) Write-Output $Item.Name } Get-ChildItem "." -Recurse -Filter "*.txt" | ForEach-Object -Parallel { &CustomPrint -Item $_ }
错误信息:
&: The term 'CustomPrint' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. &: The term 'CustomPrint' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. &: The term 'CustomPrint' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
解答
这是预期行为,原因在于:
ForEach-Object -Parallel会为每个并行任务启动独立的PowerShell运行空间,这些运行空间默认不会继承当前会话中的自定义函数、变量等元素。普通ForEach-Object是在当前运行空间执行,所以能直接访问顶层定义的函数。
解决方法
有几种方式可以让并行脚本块访问自定义函数:
- 使用
$using:作用域传递函数
把函数作为变量传递到并行块中,再调用:
function CustomPrint { param($Item) Write-Output $Item.Name } Get-ChildItem "." -Recurse -Filter "*.txt" | ForEach-Object -Parallel { $customPrint = $using:CustomPrint &$customPrint -Item $_ }
- 在并行脚本块内部定义函数
如果函数逻辑简单,可以直接把函数定义放在并行块里:
Get-ChildItem "." -Recurse -Filter "*.txt" | ForEach-Object -Parallel { function CustomPrint { param($Item) Write-Output $Item.Name } &CustomPrint -Item $_ }
- 使用
-ArgumentList传递函数
通过参数列表把函数传入并行块:
function CustomPrint { param($Item) Write-Output $Item.Name } Get-ChildItem "." -Recurse -Filter "*.txt" | ForEach-Object -Parallel { $func, $item = $args &$func -Item $item } -ArgumentList $CustomPrint, $_
内容的提问来源于stack exchange,提问作者igg
相关产品推荐
相关产品推荐

