本文介绍了$LastExitCode=0,但 $?=False 在 PowerShell 中.将 stderr 重定向到 stdout 会导致 NativeCommandError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么 PowerShell 在下面的第二个示例中表现出令人惊讶的行为?

Why does PowerShell show the surprising behaviour in the second example below?

首先,一个理智行为的例子:

First, an example of sane behaviour:

PS C:> & cmd /c "echo Hello from standard error 1>&2"; echo "`$LastExitCode=$LastExitCode and `$?=$?"
Hello from standard error
$LastExitCode=0 and $?=True

没有意外.我将消息打印到标准错误(使用 cmdecho).我检查了变量 $?$LastExitCode.正如预期的那样,它们分别等于 True 和 0.

No surprises. I print a message to standard error (using cmd's echo). I inspect the variables $? and $LastExitCode. They equal to True and 0 respectively, as expected.

但是,如果我要求 PowerShell 通过第一个命令将标准错误重定向到标准输出,我会收到 NativeCommandError:

However, if I ask PowerShell to redirect standard error to standard output over the first command, I get a NativeCommandError:

PS C:> & cmd /c "echo Hello from standard error 1>&2" 2>&1; echo "`$LastExitCode=$LastExitCode and `$?=$?"
cmd.exe : Hello from standard error
At line:1 char:4
+ cmd <<<<  /c "echo Hello from standard error 1>&2" 2>&1; echo "`$LastExitCode=$LastExitCode and `$?=$?"
    + CategoryInfo          : NotSpecified: (Hello from standard error :String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

$LastExitCode=0 and $?=False

我的第一个问题,为什么是 NativeCommandError?

My first question, why the NativeCommandError?

其次,当cmd运行成功且$LastExitCode为0时,为什么$?为False?PowerShell 的文档关于自动变量 没有明确定义 $?.我一直认为当且仅当 $LastExitCode 为 0 时它为 True,但我的示例与此相矛盾.

Secondly, why is $? False when cmd ran successfully and $LastExitCode is 0? PowerShell's documentation about automatic variables doesn't explicitly define $?. I always supposed it is True if and only if $LastExitCode is 0, but my example contradicts that.

以下是我在现实世界中遇到这种行为的方式(简化版).真的是FUBAR.我正在从另一个调用一个 PowerShell 脚本.内部脚本:

Here's how I came across this behaviour in the real-world (simplified). It really is FUBAR. I was calling one PowerShell script from another. The inner script:

cmd /c "echo Hello from standard error 1>&2"
if (! $?)
{
    echo "Job failed. Sending email.."
    exit 1
}
# Do something else

简单地以 .job.ps1 运行它,它工作正常,并且没有发送电子邮件.但是,我是从另一个 PowerShell 脚本调用它,记录到文件 .job.ps1 2>&1 >日志.txt.在这种情况下,会发送一封电子邮件!您在脚本之外使用错误流执行的操作会影响脚本的内部行为.观察现象会改变结果.这感觉更像是量子物理学而不是脚本!

Running this simply as .job.ps1, it works fine, and no email is sent. However, I was calling it from another PowerShell script, logging to a file .job.ps1 2>&1 > log.txt. In this case, an email is sent! What you do outside the script with the error stream affects the internal behaviour of the script. Observing a phenomenon changes the outcome. This feels like quantum physics rather than scripting!

[有趣的是:.job.ps1 2>&1 可能会或不会爆炸,这取决于你在哪里运行它]

[Interestingly: .job.ps1 2>&1 may or not blow up depending on where you run it]

推荐答案

这个错误是 PowerShell 的错误处理规范设计的不可预见的后果,因此很可能永远不会被修复.如果您的脚本只与其他 PowerShell 脚本一起运行,那么您就安全了.但是,如果您的脚本与来自广阔世界的应用程序交互,则此错误可能会咬人.

This bug is an unforeseen consequence of PowerShell's prescriptive design for error handling, so most likely it will never be fixed. If your script plays only with other PowerShell scripts, you're safe. However if your script interacts with applications from the big wide world, this bug may bite.

PS> nslookup microsoft.com 2>&1 ; echo $?

False

明白了!尽管如此,经过一些痛苦的抓挠,你永远不会忘记这个教训.

Gotcha! Still, after some painful scratching, you'll never forget the lesson.

这篇关于$LastExitCode=0,但 $?=False 在 PowerShell 中.将 stderr 重定向到 stdout 会导致 NativeCommandError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-03 05:52