Powershell:如何从PsJob内部的进程中返回退出代码?

时间:2011-12-26 10:08:33

标签: powershell

我在powershell中有以下工作:

$job = start-job {
  ...
  c:\utils\MyToolReturningSomeExitCode.cmd
} -ArgumentList $JobFile

如何访问c:\utils\MyToolReturningSomeExitCode.cmd返回的退出代码?我已经尝试了几个选项,但我唯一能找到的选项就是:

$job = start-job {
  ...
  c:\utils\MyToolReturningSomeExitCode.cmd
  $LASTEXITCODE
} -ArgumentList $JobFile

...

# collect the output
$exitCode = $job | Wait-Job | Receive-Job -ErrorAction SilentlyContinue
# output all, except the last line
$exitCode[0..($exitCode.Length - 2)]
# the last line is the exit code
exit $exitCode[-1]

我发现这种方法对我细腻的味道太过苛刻。任何人都可以提出更好的解决方案吗?

重要,我在文档中读到必须以管理员身份运行powershell才能使与作业相关的远程处理工作正常运行。我无法以管理员身份运行它,因此-ErrorAction SilentlyContinue。所以,我正在寻找不需要管理员权限的解决方案。

感谢。

2 个答案:

答案 0 :(得分:14)

如果您需要的是在主要脚本执行其他操作时在后台执行某些操作,那么PowerShell类就足够了(并且通常更快)。除此之外,它允许传入一个活动对象,以便除了通过参数输出之外还返回一些内容。

$code = @{}

$job = [PowerShell]::Create().AddScript({
  param($JobFile, $Result)
  cmd /c exit 42
  $Result.Value = $LASTEXITCODE
  'some output'
}).AddArgument($JobFile).AddArgument($code)

# start thee job
$async = $job.BeginInvoke()

# do some other work while $job is working
#.....

# end the job, get results
$job.EndInvoke($async)

# the exit code is $code.Value
"Code = $($code.Value)"

更新

原始代码是[ref]对象。它适用于PS V3 CTP2,但在V2中不起作用。所以我更正了它,我们可以使用其他对象,例如哈希表,以便通过参数返回一些数据。

答案 1 :(得分:8)

根据退出代码检测后台作业是否失败的一种方法是评估后台作业本身内的退出代码,如果退出代码指示发生错误,则抛出异常。例如,请考虑以下示例:

$job = start-job {
    # ...
    $output = & C:\utils\MyToolReturningSomeExitCode.cmd 2>&1
    if ($LASTEXITCODE -ne 0) {
        throw "Job failed. The error was: {0}." -f ([string] $output)
    }
} -ArgumentList $JobFile

$myJob = Start-Job -ScriptBlock $job | Wait-Job 
if ($myJob.State -eq 'Failed') {
    Receive-Job -Job $myJob
}

本例中有几点需要注意。我正在将标准错误输出流重定向到标准输出流,以捕获批处理脚本中的所有文本输出,如果退出代码非零则表示无法运行,则返回它。通过以这种方式抛出异常,后台作业对象State属性将让我们知道作业的结果。