我正在编写一些 PowerShell 脚本来执行一些构建自动化。我发现here https://stackoverflow.com/a/4917997/1977871 that echo $?根据先前的语句返回 true 或 false。我刚刚发现 echo 是写输出. 写主机 $?也有效。但我还是不清楚这是怎么回事$?作品。有人可以对此说几句话吗?正在搜索 echo $?网上并没有给我太多。
来补充马丁·布兰德尔的有用回答 https://stackoverflow.com/a/39865555/45375更详细的信息:
tl;dr
-
自动变量$?
(see Get-Help about_Automatic Variables https://technet.microsoft.com/en-us/library/hh847768.aspx)包含一个Boolean这反映了whether 任何非终止的发生了错误 in the 最近的陈述.
- Since
$?
是在之后设置的every声明,您必须在利益声明之后立即检查它,或者保存它以供以后检查。
- 请参阅下文了解潜在的违反直觉的行为。
-
自动变量$LASTEXITCODE
补充这通过记录特定的退出代码最近执行的外部命令行实用程序(控制台应用程序,例如findstr
).
-
$LASTEXITCODE
补充$?
在那里面$?
仅反映abstract外部实用程序成功或失败 - 退出代码0
被映射到$True
,任何非零退出代码$False
- 然而$LASTEXITCODE
包含实际的退出代码。
- Since
$LASTEXITCODE
仅为外部命令行实用程序设置,其值通常保持有效的时间长于$?
,这是在之后设置的every陈述。
有许多微妙之处围绕如何$?
已设置,并且其值准确地表示什么:
-
在 PowerShell 版本中v7.2 之前的版本, $?
有一个外部命令行实用程序的误报风险,即它可以报告$false
即使当$LASTEXITCODE
is 0
,即当2>
使用重定向并且存在实际的 stderr 输出 - 请参阅这个答案 https://stackoverflow.com/a/66726535/45375了解详情。
-
$?
只反映了发生不终止的 errors,因为(更为罕见)终止默认情况下,错误会终止当前命令行/脚本的执行,要处理它们,您需要使用try / catch
(首选)或trap
(参见Get-Help about_Try_Catch_Finally https://technet.microsoft.com/en-us/library/hh847793.aspx and Get-Help about_Trap https://technet.microsoft.com/en-us/library/hh847742.aspx).
- 相反,您可以选择使用首选项变量将非终止错误视为终止错误
$ErrorActionPreference
或通用 cmdlet 参数
-ErrorAction
(alias -EA
) - see Get-Help about_Preference_Variables https://technet.microsoft.com/en-us/library/hh847796.aspx and Get-Help about_CommonParameters http://go.microsoft.com/fwlink/?LinkID=113216.
-
除非明确ignored(与常见的-ErrorAction Ignore
cmdlet 参数),所有非终止错误(和捕获的终止错误)都收集在自动$Error
收藏,按时间倒序排列;即元素$Error[0]
包含最近的错误。
-
对于命令multiple输入对象被传递,$?
含有$False
只告诉你处理最后一个输入对象失败。换句话说:可能发生错误任何子集输入对象的数量,包括他们全部.
- 要确定确切的错误计数和有问题的输入对象,您必须检查
$Error
收藏。
-
With 非远程间接执行 cmdlets您向其传递要执行的目标命令 - 例如Invoke-Expression
, Start-Process
and Start-Job
and Invoke-Command
without the -ComputerName
参数(不涉及远程处理 - 见下文)-$?
只反映目标命令是否可以被调用原则,无论该命令是否报告错误。
- 一个简单的例子:
Invoke-Expression '1 / 0'
sets $?
to $True
(!), 因为Invoke-Expression
能够解析并invoke表达式,即使表达式本身失败了。
- 再次,检查
$Error
集合告诉您目标命令是否报告了错误以及报告了哪些错误。
-
With remoting(总是间接执行)cmdlet,特别是与Invoke-Command
与-ComputerName
参数(这是典型的),但也可以使用隐式远程处理 cmdlet,$?
does反映是否目标命令报告任何错误。
-
A simple example (must be run from an elevated console and assumes that the local machine is already set up for remoting):
Invoke-Command -ComputerName . { 1 / 0 }
, because remoting is involved, indeed sets $?
to $False
to reflects the failure of target command 1 / 0
.
Note that even though the local computer (.
) is targeted, use of -ComputerName
invariably uses remoting.
-
请注意,根据设计,远程处理通常会报告终止远程发生的错误非终止的可能是这样,一台目标机器上的正常终止错误不会中止所有其他机器上的处理。
-
确实反映错误的命令示例$?
:
# Invoking a non-existing cmdlet or utility directly.
NoSuchCmd
# Ditto, via call operator &.
# Note, however, that using a *script block* with & behaves differently - see below.
& 'NoSuchCmd'
# Invoking a cmdlet with invalid parameter syntax.
Get-ChildItem -NoSuchParameter
# Invoking a cmdlet with parameter values that cause a (non-terminating) runtime error.
Get-ChildItem NoSuchFile
# Invoking an external utility that reports a nonzero exit code.
findstr -nosuchoptions
# The specific exit code is recorded in $LASTEXITCODE,
# until the next external utility is called.
# Runtime exceptions
1 / 0
# A cmdlet that uses remoting:
# (Must be run from an elevated session, and the local machine must
# be configured for remoting first - run `winrm quickconfig`).
# Note that remoting would NOT be involved WITHOUT the -ComputerName parameter,
# in which case `$?` would only reflect whether the script block could be
# _invoked_, irrespective of whether its command(s) then fail or not.
Invoke-Command -ComputerName . { 1 / 0 }
# A .NET method that throws an exception.
# Note: Outside of a `try/catch` handler, this is a non-terminating error.
# Inside a `try/catch` handler, .NET exceptions are treated as terminating
# and trigger the `catch` block.
[System.IO.Path]::IsPathRooted('>')
-
不反映错误的命令示例$?
:
<#
Non-remoting indirect execution cmdlets:
$? reflects only whether the specified command could be
*invoked*, irrespective of whether the command itself then failed or not.
In other words: $? is only $False if the specified command could not even be
executed, such as due to invalid parameter syntax, an ill-formed target
command, or a missing target executable.
#>
# Invoking a command stored in a script block.
& { 1 / 0 }
# Invoking an expression stored in a string.
Invoke-Expression '1 / 0'
# Starting a background job.
Start-Job { 1/ 0 }
# The *non-remoting* form of Invoke-Command (WITHOUT -ComputerName).
Invoke-Command { 1 / 0 }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)