Если вы хотите, чтобы функция запускала произвольную команду и выдавала ошибку в случае сбоя этой команды, вы могли бы сделать что-то вроде этого:
function Test-Command {
try {
$cmd, $params = $args
$params = @($params)
$global:LastExitCode = 0
$output = & $cmd @params 2>&1
if ($global:LastExitCode -ne 0) {
throw $output
}
$output
} catch {
throw $_
}
}
Разбивка:
$cmd, $params = $args
принимает автоматическая переменная $args
(массив аргументов, переданных функции) и присваивает свой первый элемент переменной $cmd
, а остальные - переменной $params
.
$params = @($params)
гарантирует, что $params
содержит массив (требуется для следующего шага), даже если переменная была пустой или содержала только одно значение.
& $cmd @params
вызывает команду, используя оператор вызова &
при разбрызгивании параметров. Do NOT use Invoke-Expression
.
Оператор перенаправления 2>&1
объединяет вывод ошибок с нормальным выводом, так что оба выходных потоказаписывается в переменную $output
.
Если $cmd
является командлетом PowerShell , то возникнет исключение, которое перехватывается оператором try
.Остальная часть кода в блоке try
будет пропущена.Однако обратите внимание, что не все ошибки, выдаваемые командлетами PowerShell, автоматически завершают ошибки (см., Например, «Введение в обработку ошибок в PowerShell» в блоге «Сценарист»).Чтобы превратить не завершающие ошибки в завершающие, вам нужно установить $ErrorActionPreference = 'Stop'
(и вернуть его к исходному значению после того, как вы это сделаете).
Если $cmd
- это внешняя команда ошибки не вызовут исключений, но автоматическая переменная $LastExitCode
обновляется с помощью кода выхода команды.Команда, возвращающая ненулевой код завершения, вызовет условие if
и вызовет пользовательское исключение, используя вывод команды в качестве сообщения об исключении.Это исключение затем перехватывается оператором try
.Остальная часть кода в блоке try
снова пропускается.
$global:LastExitCode = 0
сбрасывает переменную $LastExitCode
перед каждым запуском.Это необходимо, поскольку только внешние команды возвращают код завершения, а командлеты PowerShell - нет.Так как $LastExitCode
сохраняет код завершения внешней команды, которая последний раз выполнялась в текущем сеансе, отсутствие сброса переменной может помешать обнаружению состояния командлета PowerShell, выполненного после внешней команды.
Последняя строка в *Блок 1067 *, который повторяет захваченный вывод команды, достигается только в том случае, если команда не выдает исключение и не возвращает ненулевой код выхода.
Любое перехваченное исключение обрабатывается в блоке catch
, который простопередает исключение вызывающей функции.Вместо броска вы можете также вывести ошибку и выйти, конечно.