Powershell: Как получить код выхода, возвращаемый процессом, запущенным внутри PsJob? - PullRequest
16 голосов
/ 26 декабря 2011

У меня есть следующая работа в 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 ]

14 голосов
/ 26 декабря 2011

Если все, что вам нужно, это сделать что-то в фоновом режиме, в то время как основной сценарий делает что-то еще, тогда достаточно 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.Поэтому я исправил это, вместо этого мы можем использовать другие объекты, например, хеш-таблицу, чтобы возвращать некоторые данные через параметры.

8 голосов
/ 26 декабря 2011

Один из способов определить, не удалось ли фоновое задание или нет на основе кода завершения, - это оценить код завершения внутри самого фонового задания и выдать исключение, если код завершения указывает на возникшую ошибку. Например, рассмотрим следующий пример:

$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 объекта фонового задания сообщит нам результат задания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...