Local Function Calls Not Working When Making Use of Start-Job

前端 未结 2 1539
旧巷少年郎
旧巷少年郎 2021-01-24 06:46
       function F2([String]$var2)
        {
         .........
         .........
        }

       function F1([String]$var1)
        {
         .........
         F2 $         


        
2条回答
  •  情歌与酒
    2021-01-24 07:43

    This is practically the same answer as Dong Mao's, which was here first, but I wrote it on the duplicate without realizing this was here.

    Anyway, this method (using modules) may better address the scaling and duplication of code issue.


    It's not so much that F2 is out of scope, it's that it doesn't even exist in the job.

    Jobs are run as separate processes, so nothing is included from the calling process unless you explicitly give it.

    When you reference ${function:F1} you're using the PSDrive form of variable. In essence, it is the equivalent of Get-Content -LiteralPath Function:\F1.

    If you look at what is returned, you'll see that 1) it's a [ScriptBlock] (which is exactly the type you need for Start-Job's -ScriptBlock parameter), but you'll also see that it is the function's contents; it doesn't even include the name.

    This means that in the job you're directly executing the body of the function but you are not actually calling a function.

    You could work around this re-generating the function definition part, defining the functions, or just defining F2 over again in the script block. This will start to get messy quickly.

    Use a Module

    My recommendation is to break your functions out into a module that is available on the system, then inside the script block, just call Import-Module MyFunctions and they will be available.

    If you don't want to go through that process of having separate files, and want to keep it contained, you can create a module on the fly. Just define your functions as a module in your script, and if you like, do it again in the job. Something like this:

    $moduleDefinition = {
        function F2([String]$var2)
        {
            "~$var2~"
        }
    
        function F1([String]$var1)
        {
            F2 $var1
        }
    }
    
    # this makes the module loaded in this context
    New-Module -Name MyFunctions -ScriptBlock $moduleDefinition
    
    while ($i -le $count)
    {
        F1 "dir$i"
        Start-Job -ScriptBlock { 
            param([String]$jobArg)
    
            $modDef = [ScriptBlock]::Create($Using:moduleDefinition)    
            New-Module -Name MyFunctions -ScriptBlock $modDef
    
            F1 $jobArg
        } -ArgumentList @($i)
        $i = $i + 1
    }
    

提交回复
热议问题