web-dev-qa-db-ja.com

「Invoke-Expression」のステータスを取得する方法、成功または失敗?

Invoke-Expressionは、呼び出されるコマンドのすべてのテキストを返します。

しかし、このコマンドが正常に実行されたか失敗して実行されたかどうかのシステム戻り値を取得するにはどうすればよいですか? CMDでは%errorlevel%外部コマンドの実行状態を取得します。 PowerShellについてはどうですか?

15
vik santata

通常、$?を使用して、最後に実行されたステートメントのステータスを検査します。

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
}

しかし、パイプライン出力がないことに依存しています

18

PowerShellでは、 自動変数 を検査して実行ステータスを評価できます

$?
   Contains True if last operation succeeded and False otherwise.

および/または

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

前者はPowerShellコマンドレット用、後者は外部コマンド用(バッチスクリプトの%errorlevel%など)です。

これは役に立ちますか?

10
Ruts

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の定義がグローバルに設定された定義を非表示にするためだと思います。

2
Konrad Jamrozik

$ 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
0
theosophe74