当外部命令(例如git)写入stderr时,PowerShell会生成NativeCommandError异常。我希望看到输出和stdout正常,类似于标准UNIX/Linux系统上的输出。该脚本需要运行许多 native 命令,我希望有一种解决方案,该解决方案在可能的情况下不会给每个命令增加过多的困惑和维护。
在Linux上,可以按以下方式 check out 分支:
$ git checkout devel
Branch 'devel' set up to track remote branch 'devel' from 'origin'.
Switched to a new branch 'devel'
最微妙的部分是,无论出于何种原因,最后一行都写到了stderr上。但是,git的退出状态为零,表明成功。在PowerShell下,我得到以下信息:
PS> git checkout devel
Branch 'devel' set up to track remote branch 'devel' from 'origin'.
git : Switched to a new branch 'devel'
At line:1 char:1
+ git checkout devel
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (Switched to a new branch 'devel':String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
正在检查
$LASTEXITSTATUS
,它显示为零,指示结帐成功。但是,由于git的行为是向stderr写入某些消息,因此它会触发PowerShell注册错误。我可以只 stash 消息并手动检查退出状态,但是我不想在显示错误消息时 stash 它们。此命令可避免出现以下异常:PS> git checkout devel 2>$null
Branch 'devel' set up to track remote branch 'devel' from 'origin'.
这是StackOverflow上其他答案的建议,但不是我所需要的。我尝试将stderr重定向到stdout,希望PowerShell可以在stdout上看到所有输出,并且不会触发异常,但是它仍然可以:
git checkout devel 2>&1
Branch 'devel' set up to track remote branch 'devel' from 'origin'.
git : Switched to a new branch 'devel'
At line:1 char:1
+ git checkout devel 2>&1
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (Switched to a new branch 'devel':String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
我也 try catch 异常,但是try..catch块似乎没有阻止它:
PS> Try { git checkout devel 2>&1 } catch { echo "There was an error, ignore" }
Branch 'devel' set up to track remote branch 'devel' from 'origin'.
git : Switched to a new branch 'devel'
At line:1 char:7
+ Try { git checkout devel 2>&1 } catch { echo "There was an error, ign ...
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (Switched to a new branch 'devel':String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
我只希望 native 命令在退出状态为非零时导致失败,而不是仅写入stderr时导致失败。如何防止PowerShell脚本中的 native 命令在写入stderr时引发异常而不完全阻止stderr?
最佳答案
tl;博士
以下是PowerShell ISE 的最简单的解决方法(在常规控制台或Visual Studio Code中不需要):
# Redirect stderr (2) to the success stream (1).
# Doing so wraps stderr lines in [System.Management.Automation.ErrorRecord]
# instances; calling .ToString() on them returns them as normal text.
# CAVEAT: BE SURE THAT $ErrorActionPreference = 'Stop' is NOT IN EFFECT.
git checkout devel 2>&1 | % ToString
有关其他变通方法,包括能够按来源流区分线的功能,请参见this answer。
但是,您最好改用Visual Studio Code 作为您的开发环境,这从根本上解决了该问题-参见下文。
两个方面:
[System.Management.Automation.ErrorRecord]
实例中,并且可能会(也可能不会)中止执行(终止与非终止错误)。 try
/catch
不会捕获非终止错误,只会终止错误。尽管您可以预先设置$ErrorActionPreference = 'Stop'
来将非终止错误升级为终止错误,但是在接收到第一条stderr行时,将终止程序(在ISE中)的执行。 如果将PowerShell的使用范围限制为:,您可以避免此问题。
这些环境的行为符合您的预期:
笔记:
2>
与外部程序一起使用,还存在其他,独立于主机的问题。 有关所有问题的全面概述,请参见this answer。
关于git - 从外部命令向stderr写入时不要抛出PowerShell异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59366288/