如何获取 "Invoke-Expression" 的状态,成功或失败?
How to get status of "Invoke-Expression", successful or failed?
Invoke-Expression
将 return 调用命令的所有文本。
但是如何获取系统return这个命令执行成功还是失败的值呢?在 CMD 中,我可以使用 %errorlevel%
来获取外部命令执行状态。 PowerShell 呢?
在 PowerShell 中,您可以通过检查 automatic variables
来评估执行状态
$?
Contains True if last operation succeeded and False otherwise.
and/or
$LASTEXITCODE
Contains the exit code of the last Win32 executable execution.
前者用于 PowerShell cmdlet,后者用于外部命令(如批处理脚本中的 %errorlevel%
)。
这对你有帮助吗?
通常你会使用$?
来检查最后执行语句的状态:
PS C:\> Write-Output 123 | Out-Null; $?
True
PS C:\> Non-ExistingCmdlet 123 | Out-Null; $?
False
但是,这不适用于 Invoke-Expression
,因为即使传递给 Invoke-Expression
的表达式中的语句可能会失败,Invoke-Expression
调用它 self 也会成功(即表达式,虽然 invalid/non-functional 被调用 none the less)
使用 Invoke-Expression
你必须使用 try:
try {
Invoke-Expression "Do-ErrorProneAction -Parameter $argument"
} catch {
# error handling go here, $_ contains the error record
}
或陷阱:
trap {
# error handling goes here, $_ contains the error record
}
Invoke-Expression "More-ErrorProneActions"
替代方法是将 ";$?"
附加到您要调用的表达式:
$Expr = "Write-Host $SomeValue"
$Expr += ';$?'
$Success = Invoke-Expression $Expr
if(-not $Success){
# seems to have failed
}
但依赖于没有任何管道输出
$LASTEXITCODE 不能与 Invoke-Expression 一起使用,因为无论调用的表达式是成功还是失败,它都将为零:
PS C:\Users\myUserAccount> touch temp.txt
PS C:\Users\myUserAccount> Invoke-Expression "Remove-Item .\temp.txt"
PS C:\Users\myUserAccount> echo $LASTEXITCODE
0
PS C:\Users\myUserAccount> Invoke-Expression "Remove-Item .\temp.txt"
Remove-Item : Cannot find path 'C:\Users\myUserAccount\temp.txt' because it does not
exist.
At line:1 char:1
+ Remove-Item .\temp.txt
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Users\myUserAccount\temp.txt:String) [Remove-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand
PS C:\Users\myUserAccount> echo $LASTEXITCODE
0
如果Invoke-Expression
调用的可执行文件支持,可以使用$LASTEXITCODE
。不过,您必须小心变量范围。
function foo
{
$global:LASTEXITCODE = 0 # Note the global prefix.
Invoke-Expression "dotnet build xyz" # xyz is meaningless, to force nonzero exit code.
Write-Host $LASTEXITCODE
}
foo
如果你运行它,输出将是:
Microsoft (R) Build Engine version 15.9.20+g88f5fadfbe for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
MSBUILD : error MSB1009: Project file does not exist.
Switch: xyz
1
观察末尾的 1,表示非零退出代码。
如果您忘记了 global:
前缀,那么输出将是 0。我相信这是因为 LASTEXITCODE
的函数范围定义会隐藏全局设置的。
我找到了一种简单的方法,它可以保持 STDOUT 的完整性。
$Expr="MY EXPRESSION"
$Expr += '; $Success=$?'
Invoke-Expression $Expr
成功现在是 True 或 False,所有 IO 保持不变。
Invoke-Expression
将 return 调用命令的所有文本。
但是如何获取系统return这个命令执行成功还是失败的值呢?在 CMD 中,我可以使用 %errorlevel%
来获取外部命令执行状态。 PowerShell 呢?
在 PowerShell 中,您可以通过检查 automatic variables
来评估执行状态$?
Contains True if last operation succeeded and False otherwise.
and/or
$LASTEXITCODE
Contains the exit code of the last Win32 executable execution.
前者用于 PowerShell cmdlet,后者用于外部命令(如批处理脚本中的 %errorlevel%
)。
这对你有帮助吗?
通常你会使用$?
来检查最后执行语句的状态:
PS C:\> Write-Output 123 | Out-Null; $?
True
PS C:\> Non-ExistingCmdlet 123 | Out-Null; $?
False
但是,这不适用于 Invoke-Expression
,因为即使传递给 Invoke-Expression
的表达式中的语句可能会失败,Invoke-Expression
调用它 self 也会成功(即表达式,虽然 invalid/non-functional 被调用 none the less)
使用 Invoke-Expression
你必须使用 try:
try {
Invoke-Expression "Do-ErrorProneAction -Parameter $argument"
} catch {
# error handling go here, $_ contains the error record
}
或陷阱:
trap {
# error handling goes here, $_ contains the error record
}
Invoke-Expression "More-ErrorProneActions"
替代方法是将 ";$?"
附加到您要调用的表达式:
$Expr = "Write-Host $SomeValue"
$Expr += ';$?'
$Success = Invoke-Expression $Expr
if(-not $Success){
# seems to have failed
}
但依赖于没有任何管道输出
$LASTEXITCODE 不能与 Invoke-Expression 一起使用,因为无论调用的表达式是成功还是失败,它都将为零:
PS C:\Users\myUserAccount> touch temp.txt
PS C:\Users\myUserAccount> Invoke-Expression "Remove-Item .\temp.txt"
PS C:\Users\myUserAccount> echo $LASTEXITCODE
0
PS C:\Users\myUserAccount> Invoke-Expression "Remove-Item .\temp.txt"
Remove-Item : Cannot find path 'C:\Users\myUserAccount\temp.txt' because it does not
exist.
At line:1 char:1
+ Remove-Item .\temp.txt
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Users\myUserAccount\temp.txt:String) [Remove-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand
PS C:\Users\myUserAccount> echo $LASTEXITCODE
0
如果Invoke-Expression
调用的可执行文件支持,可以使用$LASTEXITCODE
。不过,您必须小心变量范围。
function foo
{
$global:LASTEXITCODE = 0 # Note the global prefix.
Invoke-Expression "dotnet build xyz" # xyz is meaningless, to force nonzero exit code.
Write-Host $LASTEXITCODE
}
foo
如果你运行它,输出将是:
Microsoft (R) Build Engine version 15.9.20+g88f5fadfbe for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
MSBUILD : error MSB1009: Project file does not exist.
Switch: xyz
1
观察末尾的 1,表示非零退出代码。
如果您忘记了 global:
前缀,那么输出将是 0。我相信这是因为 LASTEXITCODE
的函数范围定义会隐藏全局设置的。
我找到了一种简单的方法,它可以保持 STDOUT 的完整性。
$Expr="MY EXPRESSION"
$Expr += '; $Success=$?'
Invoke-Expression $Expr
成功现在是 True 或 False,所有 IO 保持不变。