Powershell start-job -scriptblock无法识别同一文件中定义的函数?

ca9*_*3d9 13 powershell powershell-2.0

我有以下代码.

function createZip
{
Param ([String]$source, [String]$zipfile)
Process { echo "zip: $source`n     --> $zipfile" }
}

try {
    Start-Job -ScriptBlock { createZip "abd" "acd" } 
}
catch {
    $_ | fl * -force
}
Get-Job | Wait-Job 
Get-Job | receive-job 
Get-Job | Remove-Job 
Run Code Online (Sandbox Code Playgroud)

但是,该脚本返回以下错误.

Id              Name            State      HasMoreData     Location             Command                  
--              ----            -----      -----------     --------             -------                  
309             Job309          Running    True            localhost            createZip "a...
309             Job309          Failed     False           localhost            createZip "a...
Receive-Job : The term 'createZip' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:17 char:22
+ Get-Job | receive-job <<<<  
    + CategoryInfo          : ObjectNotFound: (function:createZip:String) [Receive-Job], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
Run Code Online (Sandbox Code Playgroud)

似乎在脚本块中无法识别函数名称start-job.我也试过function:createZip了.

And*_*ndi 15

Start-Job实际上旋转了另一个没有createZip函数的PowerShell.exe实例.您需要将它全部包含在脚本块中:

$createZip = {
    param ([String]$source, [String]$zipfile)
    Process { echo "zip: $source`n     --> $zipfile" }
}

Start-Job -ScriptBlock $createZip  -ArgumentList "abd", "acd"
Run Code Online (Sandbox Code Playgroud)

从后台作业返回错误消息的示例:

$createZip = {
    param ([String] $source, [String] $zipfile)

    $output = & zip.exe $source $zipfile 2>&1
    if ($LASTEXITCODE -ne 0) {
        throw $output
    }
}

$job = Start-Job -ScriptBlock $createZip -ArgumentList "abd", "acd"
$job | Wait-Job | Receive-Job
Run Code Online (Sandbox Code Playgroud)

另请注意,使用throw作业对象State将"失败",因此您只能获得失败的作业:Get-Job -State Failed.


Con*_*d B 6

如果您还不熟悉使用start-job和receive-job,并且想要更轻松地调试函数,请尝试以下形式:

   $createZip = { 
   function createzipFunc {
     param ([String]$source, [String]$zipfile)
     Process { echo "zip: $source`n     --> $zipfile" }
     }
     #other funcs and constants here if wanted...
   }
   # some secret sauce, this defines the function(s) for us as locals
   invoke-expression $createzip

   #now test it out without any job plumbing to confuse you
   createzipFunc "abd" "acd"

   # once debugged, unfortunately this makes calling the function from the job  
   # slightly harder, but here goes...
   Start-Job -initializationScript $createZip -scriptblock {param($a,$b) `
createzipFunc $a $b } -ArgumentList "abc","def"
Run Code Online (Sandbox Code Playgroud)

所有这一切并不简单,因为我没有将我的函数定义为一个简单的过滤器,但我之所以这样做,是因为我想最终将一些函数传递给我的Job.

很抱歉挖出这个帖子,但它也解决了我的问题,并且非常优雅.所以我只需要在调试我的powershell工作时添加一些我写过的酱汁.

  • 我喜欢这种方法.要添加的一件事有时候`Invoke-Expression`会抱怨`Invoke-Expression:无法评估参数'Command',因为它的参数被指定为脚本块并且没有输入.没有输入就无法评估脚本块.我发现如果你将变量作为字符串`invoke-expression'传递,$ createzip"`解决了这个问题. (2认同)