如何开始我刚刚定义的函数的工作?

问题描述 投票:0回答:8

如何开始我刚刚定义的函数的工作?

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.

我该怎么办? 谢谢。

powershell jobs
8个回答
37
投票

正如@Shay 指出的,需要为该工作定义

FOO
。另一种方法是使用
-InitializationScript
参数来准备会话。

举个例子:

$functions = {
    function FOO { write-host "HEY" }
}

Start-Job -InitializationScript $functions -ScriptBlock {FOO}|
    Wait-Job| Receive-Job

如果您想对不同的工作使用相同的功能,这会很有用。


13
投票

@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

9
投票

它对我有用:

Start-Job -ScriptBlock ${Function:FOO}

5
投票

对@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

我喜欢这种方式,因为通过在调试器下本地运行作业来调试作业更容易。


3
投票

该函数需要位于脚本块内:

Start-Job -ScriptBlock { function FOO { write-host "HEY" } ; FOO } | Wait-Job | Receive-Job

1
投票

只要 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

0
投票

略有不同的看法。函数只是分配给变量的脚本块。哦,那一定是线程作业。它不能是 foreach-object -parallel。

$func = { 'hi' } # or
function hi { 'hi' }; $func = $function:hi

start-threadjob { & $using:func } | receive-job -auto -wait

hi

0
投票

@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
© www.soinside.com 2019 - 2024. All rights reserved.