如何获得“Invoke-Expression”状态,成功还是失败?

时间:2015-09-02 08:58:24

标签: powershell exit-code

Invoke-Expression将返回被调用命令的所有文本。

但是如何获得系统返回值,表明该命令是成功执行还是失败?在CMD中,我可以使用%errorlevel%来获取外部命令执行状态。 PowerShell怎么样?

5 个答案:

答案 0 :(得分:18)

通常你会使用$?检查最后执行的语句的状态:

PS C:\> Write-Output 123 | Out-Null; $?
True
PS C:\> Non-ExistingCmdlet 123 | Out-Null; $?
False

然而,这不能与Invoke-Expression一起使用,因为即使传递给Invoke-Expression的表达式中的语句可能会失败,Invoke-Expression自我调用也会成功(即表达式,尽管无效地调用了无效/非功能性

使用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
}

但依赖于没有任何管道输出

答案 1 :(得分:9)

在PowerShell中,您可以通过检查automatic variables

来评估执行状态
$?
   Contains True if last operation succeeded and False otherwise.

和/或

$LASTEXITCODE
   Contains the exit code of the last Win32 executable execution.

前者适用于PowerShell cmdlet,后者适用于外部命令(如批处理脚本中的%errorlevel%)。

这对你有帮助吗?

答案 2 :(得分:1)

$ 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

答案 3 :(得分:1)

如果$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

如果运行它,输出将是:

global:

观察结尾处的1,表示非零退出代码。

如果您忘记了LASTEXITCODE前缀,那么输出将为0。我相信这是因为您的函数范围定义library(lubridate) start <- c("2007-09-16 18:40:27 GMT","2007-09-28 23:53:55 GMT", "2007-10-25 05:23:01 GMT") end <- c("2007-09-19 18:40:27 GMT", "2007-10-01 23:53:55 GMT","2007-10-28 05:23:01 GMT") inc <- c("2007-09-17 18:45:00 GMT", "2007-09-17 19:00:00 GMT", "2007-09-17 19:15:00 GMT", "2007-09-17 19:30:00 GMT") inc <- as_datetime(inc) start <- min(as_date(start)) end <- max(as_datetime(end)) inc[which(inc >= start & inc <= end)] > inc[which(inc >= start & inc <= end)] [1] "2007-09-17 18:45:00 UTC" "2007-09-17 19:00:00 UTC" "2007-09-17 19:15:00 UTC" "2007-09-17 19:30:00 UTC" 会隐藏全局设置之一。

答案 4 :(得分:1)

我找到了一种简单的方法来保持STDOUT完好无损。

$Expr="MY EXPRESSION"
$Expr += '; $Success=$?'
Invoke-Expression $Expr

成功现在为True或False,并且所有IO都保持不变。