如何开始我刚刚定义的函数的工作?
function FOO { write-host "HEY" }
Start-Job -ScriptBlock { FOO } |
Receive-Job -Wait -AutoRemoveJob
结果:
Receive-Job: The term 'FOO' is not recognized as the name of cmdlet,
function ,script file or operable program.
我该怎么办? 谢谢。
正如@Shay 指出的,需要为该工作定义
FOO
。另一种方法是使用 -InitializationScript
参数来准备会话。
举个例子:
$functions = {
function FOO { write-host "HEY" }
}
Start-Job -InitializationScript $functions -ScriptBlock {FOO}|
Wait-Job| Receive-Job
如果您想对不同的工作使用相同的功能,这会很有用。
@Rynant 的建议
InitializationScript
很棒
我认为(脚本)块的目的是为了让你可以传递它们。因此,根据您的做法,我会说:
$FOO = {write-host "HEY"}
Start-Job -ScriptBlock $FOO | wait-job |Receive-Job
当然你也可以参数化脚本块:
$foo = {param($bar) write-host $bar}
Start-Job -ScriptBlock $foo -ArgumentList "HEY" | wait-job | receive-job
它对我有用:
Start-Job -ScriptBlock ${Function:FOO}
对@Rynant 答案的改进:
您可以在脚本主体中正常定义函数:
Function FOO
{
Write-Host "HEY"
}
然后在脚本块中回收这个定义:
$export_functions = [scriptblock]::Create(@"
Function Foo { $function:FOO }
"@)
(如果你有一个实质性的函数体,则更有意义)然后将它们传递给
Start-Job
,如上所述:
Start-Job -ScriptBlock {FOO} -InitializationScript $export_functions| Wait-Job | Receive-Job
我喜欢这种方式,因为通过在调试器下本地运行作业来调试作业更容易。
该函数需要位于脚本块内:
Start-Job -ScriptBlock { function FOO { write-host "HEY" } ; FOO } | Wait-Job | Receive-Job
只要 Start-Job 上传递给 InitializationScript 参数的函数不大,Rynant 的答案就可以工作,但如果函数很大,您可能会遇到以下错误。
[localhost] 启动后台进程时出错。错误 报告:文件名或扩展名太长”
捕获函数的定义,然后在 ScriptBlock 中对其使用 Invoke-Expression 是更好的选择。
function Get-Foo {
param
(
[string]$output
)
Write-Output $output
}
$getFooFunc = $(Get-Command Get-Foo).Definition
Start-Job -ScriptBlock {
Invoke-Expression "function Get-Foo {$using:getFooFunc}"
Get-Foo -output "bar"
}
Get-Job | Receive-Job
PS C:\Users\rohopkin> Get-Job | Receive-Job
bar
略有不同的看法。函数只是分配给变量的脚本块。哦,那一定是线程作业。它不能是 foreach-object -parallel。
$func = { 'hi' } # or
function hi { 'hi' }; $func = $function:hi
start-threadjob { & $using:func } | receive-job -auto -wait
hi
@Ben Power 在已接受答案下的评论也是我关心的问题,所以我用谷歌搜索了如何获取函数定义,我发现了
Get-Command
- 尽管这只能获取函数体。但如果函数来自其他地方(例如点源文件),也可以使用它。所以我想出了以下内容(保留我的命名约定:)),想法是重新构建由换行符分隔的函数定义:
Filter Greeting {param ([string]$Greeting) return $Greeting}
Filter FullName {param ([string]$FirstName, [string]$LastName) return $FirstName + " " + $LastName}
$ScriptText = ""
$ScriptText += "Filter Greeting {" + (Get-Command Greeting).Definition + "}`n"
$ScriptText += "Filter FullName {" + (Get-Command FullName).Definition + "}`n"
$Job = Start-Job `
-InitializationScript $([ScriptBlock]::Create($ScriptText)) `
-ScriptBlock {(Greeting -Greeting "Hello") + " " + (FullName -FirstName "PowerShell" -LastName "Programmer")}
$Result = $Job | Wait-Job | Receive-Job
$Result
$Job | Remove-Job