Invoke-Expression
は、呼び出されるコマンドのすべてのテキストを返します。
しかし、このコマンドが正常に実行されたか失敗して実行されたかどうかのシステム戻り値を取得するにはどうすればよいですか? CMDでは%errorlevel%
外部コマンドの実行状態を取得します。 PowerShellについてはどうですか?
通常、$?
を使用して、最後に実行されたステートメントのステータスを検査します。
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
}
しかし、パイプライン出力がないことに依存しています
PowerShellでは、 自動変数 を検査して実行ステータスを評価できます
$?
Contains True if last operation succeeded and False otherwise.
および/または
$LASTEXITCODE
Contains the exit code of the last Win32 executable execution.
前者はPowerShellコマンドレット用、後者は外部コマンド用(バッチスクリプトの%errorlevel%
など)です。
これは役に立ちますか?
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
の定義がグローバルに設定された定義を非表示にするためだと思います。
$ 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