我找不到传递函数的方法。只有一些变量。
在不将函数放入ForEach循环的情况下,有什么想法吗?
function CustomFunction {
Param (
$A
)
Write-Host $A
}
$List = "Apple", "Banana", "Grape"
$List | ForEach-Object -Parallel {
Write-Host $using:CustomFunction $_
}
我找不到传递函数的方法。只有一些变量。
在不将函数放入ForEach循环的情况下,有什么想法吗?
function CustomFunction {
Param (
$A
)
Write-Host $A
}
$List = "Apple", "Banana", "Grape"
$List | ForEach-Object -Parallel {
Write-Host $using:CustomFunction $_
}
3条答案
按热度按时间pgx2nnw81#
解决方案并不像人们希望的那样简单:
注意:This answer包含一个类似的解决方案,用于在
ForEach-Object -Parallel
脚本块中使用调用方作用域中的脚本块。ForEach-Object -Parallel
一起工作,无需额外的工作-但每个线程都会产生(隐式)导入模块的成本。ForEach-Object -Parallel
创建的线程不会看到调用者的状态,尤其是在变量和函数方面(也不会看到自定义PS驱动器和导入的模块)。请注意,通过字符串重新定义每个线程中的函数是至关重要的,因为尝试在没有AUX的情况下凑合使用。
$funcDef
变量,并尝试使用${function:Get-Custom} = ${using:function:Get-Custom}
重新定义函数失败,因为${function:Get-Custom}
是脚本块,并且明确禁止使用带有$using:
作用域说明符的脚本块,以避免跨线程(跨运行空间)问题。${function:Get-Custom} = ${using:function:Get-Custom}
将与Start-Job
一起使用;有关示例,请参阅this answer。Start-ThreadJob
一起工作,Start-ThreadJob
目前从语法上允许您执行& ${using:function:Get-Custom} $_
,因为${using:function:Get-Custom}
被保留为脚本块*(与Start-Job
不同,在Start-Job
中,它被反序列化为字符串,这本身就是令人惊讶的行为--参见GitHub issue #11698),尽管它不应该。也就是说,直接跨线程使用[scriptblock]
示例会导致隐蔽的故障,这就是ForEach-Object -Parallel
从一开始就阻止它的原因。ForEach-Object -Parallel
也会导致跨线程问题的一个类似漏洞是通过$using:
作用域在每个线程中使用在调用者作用域中获得的命令信息对象(Get-Command
作为函数体):这也应该防止,但不是PowerShell 7.2.7-请参阅this post。${function:Get-Custom}
是namespace variable notation的一个示例,它允许您通过分配[scriptblock]
或包含函数体的字符串来获取一个函数(其主体作为[scriptblock]
示例)和设置(定义)它。7lrncoxx2#
我刚刚想出了另一种使用Get-Command的方法,它与呼叫接线员一起工作。$a最终成为FunctionInfo对象。
编辑:我被告知这不是线程安全的,但我不明白为什么。
dsekswqp3#
所以我想出了另一个小技巧,对于试图动态添加函数的人来说可能很有用,特别是如果您可能事先不知道它的名称,例如当函数在数组中时。
其中的主要“诀窍”是将
Set-Content
与Function:
和函数名一起使用,因为PowerShell基本上将Function:
的每个条目视为一个路径。当您考虑
Get-PSDrive
的输出时,这是有意义的。因为这些条目中的每一个都可以以相同的方式(即,使用冒号)用作“Drive”。