0

我从 Powrshell 调用 rabbitmqctl:

$out = (& $path ($arguments -split " ") )
Write-Host $out

使用正确的路径,输出会显示成功消息:

Clearing policy "<policyname>" on vhost "<vhost>" ...

如果路径不正确,我会遇到异常:

....
    + CategoryInfo          : NotSpecified: (Error::String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
 
Parameter does not exist

消息Clearing policy丢失。停止执行时,$_.Exception.Message 为空。

try {
   $ErrorActionPreference = 'Stop'
   ...
}
catch {
    Write-Warning $_.Exception.Message
}

有没有办法同时获取Clearing policy消息和最后一行Parameter does not exist

4

1 回答 1

2

tl;dr:将错误流重定向到stdout并将每个元素转换为字符串:

$out = (& $path ($arguments -split " ") 2>&1) | % ToString

执行外部程序(如rabbitmqctl)时,您不会收到任何异常。您可能会在不同的流中获得输出(主要是stdoutstderr),并且您的外部程序将返回错误代码,但肯定不是异常,PowerShell 可以处理。

我猜你正在使用 PowerShell ISE。为什么?因为与 PowerShell 相比,PowerShell ISE 有一个奇怪的行为,即如果强制打印从外部程序的错误流中接收到的文本,则会引发异常。

您可以使用以下命令重现它:

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肯定会捕获结果,无论是成功消息还是错误消息。在错误流的情况下,每一行都将由 a 包裹[System.Management.Automation.ErrorRecord],甚至 PowerShell(如 ISE)也会以异常的形式输出。为了防止这种情况,将每个元素转换为字符串:

$out = (& $path ($arguments -split " ") 2>&1) | % ToString

这不会对成功消息产生负面影响,因此可以在任何情况下使用。

于 2020-07-14T15:23:33.127 回答