【问题标题】:How do I Start a job of a function i just defined?如何开始我刚刚定义的函数的工作?
【发布时间】:2011-11-01 23:44:27
【问题描述】:

如何启动我刚刚定义的函数的工作?

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

Receive-Job: The term 'FOO' is not recognized as the name of cmdlet,
function ,script file or operable program.

我该怎么办? 谢谢。

【问题讨论】:

    标签: powershell jobs


    【解决方案1】:

    正如@Shay 指出的那样,需要为该工作定义FOO。另一种方法是使用-InitializationScript 参数来准备会话。

    你的例子:

    $functions = {
        function FOO { write-host "HEY" }
    }
    
    Start-Job -InitializationScript $functions -ScriptBlock {FOO}|
        Wait-Job| Receive-Job
    

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

    【讨论】:

    • 这很好,但是如何在主脚本中使用相同的功能?
    • @BenPower 请在下面查看我的答案。
    【解决方案2】:

    @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
    

    【讨论】:

    • 我同意,如果 @Alex58 想要做的只是运行一个函数,那么参数化的 ScriptBlock 就是要走的路。但如果他要定义多个函数或高级函数,InitializationScript 会很有帮助。例如:您可以在初始化脚本中定义函数FOOBAR,然后运行一个带有脚本块{FOO; BAR} 的作业和另一个带有{BAR; FOO} 的作业
    • @Rynant - 我同意。这就是为什么我说“取决于你如何做”。 PS:在我的回答中名称错误。意思是 Rynant,而不是 Matt。
    【解决方案3】:

    它对我有用:

    Start-Job -ScriptBlock ${Function:FOO}
    

    【讨论】:

    • 这对我有用,还添加了-ArgumentList。谢谢!
    【解决方案4】:

    @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
    

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

    【讨论】:

    • 我无法让它工作,该工作只输出“$function:FOO”而不是“HEY”
    • 我已经用一个绝对有效的版本更新了它。有趣,确定它以前可以工作,但可以确认旧版本不是
    • 如何使用这种语法传递参数?
    • Param 块添加到 FOO 定义,然后将 -ArgumentList $args 添加到 Start-Job 调用
    • 此技术是否适用于导出 3 个函数以及函数外部的一些代码(您将从 Start-Job 调用,然后该代码将调用这些函数)?这是我的场景,并试图弄清楚变量如何传递给函数外部的代码(但在 -ScriptBlock 内部)
    【解决方案5】:

    函数需要在脚本块内:

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

    【讨论】:

    • 我的已经完成了,不知道为什么你的还在运行。你能在一个新的实例中再次测试这个吗?
    • 我认为 xp sp3 和 posh 2.0 存在问题。现在我在 Windows 7 上,背景工作很好。我用谷歌搜索但什么也没找到。也许只是我在 xp sp3 上的个人问题。一些类似的是使用 w2k3 或 xp sp3 的 import-module 开始工作......在 w2k8 和 w2k8r2 上没有问题。
    【解决方案6】:

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

    $func = { 'hi' } # or
    function hi { 'hi' }; $func = $function:hi
    
    start-threadjob { & $using:func } | receive-job -auto -wait
    
    hi
    

    【讨论】:

      【解决方案7】:

      @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
      

      【讨论】:

        猜你喜欢
        • 2022-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-04
        • 2020-03-19
        • 2017-12-19
        相关资源
        最近更新 更多