简体   繁体   English

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

[英]Powershell: How do I get the exit code returned from a process run inside a PsJob?

I have the following job in powershell: 我在powershell中有以下工作:

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

How do I access the exit code returned by c:\\utils\\MyToolReturningSomeExitCode.cmd ? 如何访问c:\\utils\\MyToolReturningSomeExitCode.cmd返回的退出代码? I have tried several options, but the only one I could find that works is this: 我已经尝试了几个选项,但我唯一能找到的选项是:

$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]

I find this approach too wry to my delicate taste. 我发现这种方法对我细腻的味道太过苛刻。 Can anyone suggest a nicer solution? 谁能建议更好的解决方案?

Important , I have read in the documentation that powershell must be run as administrator in order for the job related remoting stuff to work. 重要的是 ,我在文档中已经读到必须以管理员身份运行powershell才能使与作业相关的远程处理工作正常运行。 I cannot run it as administrator, hence -ErrorAction SilentlyContinue . 我无法以管理员身份运行它,因此-ErrorAction SilentlyContinue So, I am looking for solutions not requiring admin privileges. 所以,我正在寻找不需要管理员权限的解决方案。

Thanks. 谢谢。

If all you need is to do something in background while the main script does something else then PowerShell class is enough (and it is normally faster). 如果您只需要在后台执行某些操作,而主脚本执行其他操作,那么PowerShell类就足够了(而且通常更快)。 Besides it allows passing in a live object in order to return something in addition to output via parameters. 除此之外,它允许传入一个活动对象,以便除了通过参数输出之外还返回一些内容。

$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)"

UPDATE UPDATE

The original code was with [ref] object. 原始代码是[ref]对象。 It works in PS V3 CTP2 but does not work in V2. 它适用于PS V3 CTP2,但在V2中不起作用。 So I corrected it, we can use other objects instead, a hashtable, for example, in order to return some data via parameters. 所以我更正了它,我们可以使用其他对象,例如哈希表,以便通过参数返回一些数据。

One way you can detect if the background job failed or not based on an exit code is to evaluate the exit code inside the background job itself and throw an exception if the exit code indicates an error occurred. 根据退出代码检测后台作业是否失败的一种方法是评估后台作业本身内的退出代码,如果退出代码指示发生错误,则抛出异常。 For instance, consider the following example: 例如,请考虑以下示例:

$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
}

A couple things of note in this example. 这个例子中有几点需要注意。 I am redirecting the standard error output stream to the standard output stream to capture all textual output from the batch script and returning it if the exit code is non-zero indicating it failed to run. 我正在将标准错误输出流重定向到标准输出流,以捕获批处理脚本中的所有文本输出,如果退出代码非零则表示无法运行,则返回它。 By throwing an exception this way the background job object State property will let us know the result of the job. 通过以这种方式抛出异常,后台作业对象State属性将让我们知道作业的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM