为什么 PowerShell 不处理这个 $?退出代码正确?
Why is PowerShell not treating this $? exit code correctly?
我想将 PowerShell 脚本编写到 select JFrog 服务连接,但脚本的行为方式与我期望的不同。
当我手动 运行 jfrog config use
命令时,它按预期工作:
PS C:\Users\rdepew> jfrog config use Dummy
[Info] Using server ID 'Dummy' (https://foo.jfrog.io/).
PS C:\Users\rdepew> $?
True
我希望能够使用始终 returns true 或 false 的 $? 来检测 jfrog config use
是否已成功执行。这个片段说明了我遇到的问题:
PS C:\Users\rdepew> if (jfrog config use Dummy) {
>> Write-Host Dummy exists
>> } else {
>> Write-Host Dummy doesnt exist but I dont believe it
>> }
[Info] Using server ID 'Dummy' (https://foo.jfrog.io/).
Dummy doesnt exist but I dont believe it
[Info] 行表明 JFrog 实际上正在使用服务器连接 'Dummy'。我假设 $?退出代码评估为真,就像我手动执行时一样。但是我的 if/else 测试采用了“if false”分支。为什么?
更多信息:如果我使用不存在的服务连接的名称,我会得到预期的行为:
PS C:\Users\rdepew> if (jfrog config use Bogus) {
>> Write-Host Bogus exists
>> } else {
>> Write-Host Bogus doesnt exist
>> }
[Error] Could not find a server with ID 'Bogus'.
Bogus doesnt exist
我不明白为什么 PS 对于 True 和 False 的情况都跳转到 else
子句。
更多信息
感谢第一位的回答和评论,让我明白了一些。我可以这样重写我的代码片段:
jfrog config add Dummy
if ($LASTEXITCODE=0) {
etc.
但我仍然对 $?行为。从命令行,$?行为如下:
PS C:\Users\rdepew> jfrog config use Dummy
[Info] Using server ID 'Dummy' (https://foo.jfrog.io/).
PS C:\Users\rdepew> $?
True
PS C:\Users\rdepew> jfrog config use Bogus
[Error] Could not find a server with ID 'Bogus'.
PS C:\Users\rdepew> $?
False
...这是人们所期望的。
在 PowerShell 中,$?
returns $true
如果之前的 cmdlet 没有错误地完成,或者 $false
如果它出现任何错误。对于外部命令,它将return $LASTEXITCODE -eq 0
.
的结果
但是,当您将命令(外部或其他)作为 if
语句中的条件时,它不会检查命令是否成功,而是检查结果的真实性。如果命令 return 是适当的 $true
或 $false
布尔值,这很简单,否则,它将成功流上的输出转换为布尔值。除以下输出之外的任何输出的计算结果为 $true
,$null
、0
、空字符串和空数组的计算结果为 $false
.
但我不确定的是为什么两个命令至少在 运行 作为 if
条件时不产生 $true
输出。另一种编写代码的方法是在 if
之外 运行 jfrog
并检查 $LASTEXITCODE
:
的结果
$output = jfrog config use Dummy
if ( $LASTEXITCODE -eq 0 ) {
Write-Host "Dummy exists"
} else {
Write-Host "Dummy doesnt exist but I dont believe it"
}
如果可以接受其他退出代码,请使用这个奇怪的技巧来检查多个值,而不必将 $LASTEXITCODE
的多个 eval 链接在一起:
# I use this often when checking the result of MSIEXEC
if ( $LASTEXITCODE -in @(0, 3010) ) {
....
}
基本上,这只是说要检查 $LASTEXITCODE
是否存在于 -in
右侧的数组中。您可以使用 -notin
来否定评估。 -contains/-notcontains
运算符也是一个选项,您只需反转 -in/-notin
.
的操作数
经过一些额外的测试,并模糊地回忆起几年前工作中的这个问题,我相信 jfrog
正在将所有内容写入 STDERR,这将解释您的行为(您可以使用 $var = jfrog blah blah blah
进行测试并查看 $var
是否包含输出或者它是否仍被写入控制台)。
如果您想减轻这种情况,例如,如果您想捕获输出,请将错误流(基本上是 STDERR)重定向到成功流(基本上是 STDOUT):
$output = jfrog blah blah blah 2>&1
但是,我仍然会依靠检查 $LASTEXITCODE
来检查失败而不是输出或 $?
。检查此问题中出现的类似问题的输出结果,并检查 $?
需要您注意将来对代码的更新,因为您可以很容易地在执行和结果评估之间插入另一个命令。
I have a comprehensive answer here 关于不同的输出流和一般的重定向,您可能会发现它们很有用。
我想将 PowerShell 脚本编写到 select JFrog 服务连接,但脚本的行为方式与我期望的不同。
当我手动 运行 jfrog config use
命令时,它按预期工作:
PS C:\Users\rdepew> jfrog config use Dummy
[Info] Using server ID 'Dummy' (https://foo.jfrog.io/).
PS C:\Users\rdepew> $?
True
我希望能够使用始终 returns true 或 false 的 $? 来检测 jfrog config use
是否已成功执行。这个片段说明了我遇到的问题:
PS C:\Users\rdepew> if (jfrog config use Dummy) {
>> Write-Host Dummy exists
>> } else {
>> Write-Host Dummy doesnt exist but I dont believe it
>> }
[Info] Using server ID 'Dummy' (https://foo.jfrog.io/).
Dummy doesnt exist but I dont believe it
[Info] 行表明 JFrog 实际上正在使用服务器连接 'Dummy'。我假设 $?退出代码评估为真,就像我手动执行时一样。但是我的 if/else 测试采用了“if false”分支。为什么?
更多信息:如果我使用不存在的服务连接的名称,我会得到预期的行为:
PS C:\Users\rdepew> if (jfrog config use Bogus) {
>> Write-Host Bogus exists
>> } else {
>> Write-Host Bogus doesnt exist
>> }
[Error] Could not find a server with ID 'Bogus'.
Bogus doesnt exist
我不明白为什么 PS 对于 True 和 False 的情况都跳转到 else
子句。
更多信息
感谢第一位的回答和评论,让我明白了一些。我可以这样重写我的代码片段:
jfrog config add Dummy
if ($LASTEXITCODE=0) {
etc.
但我仍然对 $?行为。从命令行,$?行为如下:
PS C:\Users\rdepew> jfrog config use Dummy
[Info] Using server ID 'Dummy' (https://foo.jfrog.io/).
PS C:\Users\rdepew> $?
True
PS C:\Users\rdepew> jfrog config use Bogus
[Error] Could not find a server with ID 'Bogus'.
PS C:\Users\rdepew> $?
False
...这是人们所期望的。
在 PowerShell 中,$?
returns $true
如果之前的 cmdlet 没有错误地完成,或者 $false
如果它出现任何错误。对于外部命令,它将return $LASTEXITCODE -eq 0
.
但是,当您将命令(外部或其他)作为 if
语句中的条件时,它不会检查命令是否成功,而是检查结果的真实性。如果命令 return 是适当的 $true
或 $false
布尔值,这很简单,否则,它将成功流上的输出转换为布尔值。除以下输出之外的任何输出的计算结果为 $true
,$null
、0
、空字符串和空数组的计算结果为 $false
.
但我不确定的是为什么两个命令至少在 运行 作为 if
条件时不产生 $true
输出。另一种编写代码的方法是在 if
之外 运行 jfrog
并检查 $LASTEXITCODE
:
$output = jfrog config use Dummy
if ( $LASTEXITCODE -eq 0 ) {
Write-Host "Dummy exists"
} else {
Write-Host "Dummy doesnt exist but I dont believe it"
}
如果可以接受其他退出代码,请使用这个奇怪的技巧来检查多个值,而不必将 $LASTEXITCODE
的多个 eval 链接在一起:
# I use this often when checking the result of MSIEXEC
if ( $LASTEXITCODE -in @(0, 3010) ) {
....
}
基本上,这只是说要检查 $LASTEXITCODE
是否存在于 -in
右侧的数组中。您可以使用 -notin
来否定评估。 -contains/-notcontains
运算符也是一个选项,您只需反转 -in/-notin
.
经过一些额外的测试,并模糊地回忆起几年前工作中的这个问题,我相信 jfrog
正在将所有内容写入 STDERR,这将解释您的行为(您可以使用 $var = jfrog blah blah blah
进行测试并查看 $var
是否包含输出或者它是否仍被写入控制台)。
如果您想减轻这种情况,例如,如果您想捕获输出,请将错误流(基本上是 STDERR)重定向到成功流(基本上是 STDOUT):
$output = jfrog blah blah blah 2>&1
但是,我仍然会依靠检查 $LASTEXITCODE
来检查失败而不是输出或 $?
。检查此问题中出现的类似问题的输出结果,并检查 $?
需要您注意将来对代码的更新,因为您可以很容易地在执行和结果评估之间插入另一个命令。
I have a comprehensive answer here 关于不同的输出流和一般的重定向,您可能会发现它们很有用。