tl; dr : перенаправить поток ошибок на stdout
и преобразовать каждый элемент в строку:
$out = (& $path ($arguments -split " ") 2>&1) | % ToString
При выполнении внешних программ (например, rabbitmqctl
) вы не получите никаких исключений. Вы можете получить вывод в разных потоках (в основном stdout
и stderr
), и ваша внешняя программа вернет код ошибки, но, конечно, не исключение, которое может обработать PowerShell.
Я думаю, вы используете PowerShell ISE. Зачем? Поскольку, в отличие от PowerShell, PowerShell ISE имеет странное поведение, вызывая исключение, если он вынужден печатать текст, который был получен из потока ошибок внешней программы.
Вы можете воспроизвести это с помощью следующего command:
where.exe nonExistentExecutable.bla
В PowerShell он выведет текст, говорящий, что не удалось найти файл с этим шаблоном. В PowerShell ISE вы получите исключение NativeCommandError
, которое содержит текст из потока ошибок.
Ключевым моментом здесь является то, что большинство исполняемых файлов записывают в поток ошибок, если им нужно сообщить об ошибках. Так же и where.exe
, и rabbitmqctl
в вашем случае. Вы не можете захватить поток ошибок следующим образом:
$out = (& $path ($arguments -split " ") )
Это захватит только поток успеха (он же stdout
). Поток ошибок будет перенаправлен на консоль, и ISE выдаст исключение. Вот что происходит в вашем случае. Чтобы также захватить поток ошибок, перенаправьте его на stdout
:
$out = (& $path ($arguments -split " ") 2>&1)
Теперь $out
определенно зафиксирует результат, либо сообщение об успешном выполнении, либо сообщение об ошибке. В случае потока ошибок каждая строка будет заключена в [System.Management.Automation.ErrorRecord]
, и даже PowerShell (например, ISE) выведет это в виде исключения. Чтобы этого не произошло, преобразуйте каждый элемент в строку:
$out = (& $path ($arguments -split " ") 2>&1) | % ToString
Это не повлияет отрицательно на сообщения об успешном завершении и, таким образом, может использоваться в любом случае.