Powershell从rabbitmqctl获取输出并解析异常



我正在从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

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

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

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

相关内容

  • 没有找到相关文章

最新更新