1. ホーム
  2. powershell

PowerShellの終了コードがいつも "0 "なのはなぜですか?

2023-10-07 17:41:47

質問

以下のようなPowerShellスクリプトがあります。

##teamcity[progressMessage 'Beginning build']
# If the build computer is not running the appropriate version of .NET, then the build will not run. Throw an error immediately.
if( (ls "$env:windir\Microsoft.NET\Framework\v4.0*") -eq $null ) {
    throw "This project requires .NET 4.0 to compile. Unfortunately .NET 4.0 doesn't appear to be installed on this machine."
    ##teamcity[buildStatus status='FAILURE' ]
}

##teamcity[progressMessage 'Setting up variables']
# Set up variables for the build script
$invocation = (Get-Variable MyInvocation).Value
$directorypath = Split-Path $invocation.MyCommand.Path
$v4_net_version = (ls "$env:windir\Microsoft.NET\Framework\v4.0*").Name
$nl = [Environment]::NewLine

Copy-Item -LiteralPath "$directorypath\packages\NUnit.2.6.2\lib\nunit.framework.dll" "$directorypath\Pandell.Tests\bin\debug" -Force

##teamcity[progressMessage 'Using msbuild.exe to build the project']
# Build the project using msbuild.exe.
# Note we've already determined that .NET is already installed on this computer.
cmd /c C:\Windows\Microsoft.NET\Framework\$v4_net_version\msbuild.exe "$directorypath\Pandell.sln" /p:Configuration=Release
cmd /c C:\Windows\Microsoft.NET\Framework\$v4_net_version\msbuild.exe "$directorypath\Pandell.sln" /p:Configuration=Debug

# Break if the build throws an error.
if(! $?) {
    throw "Fatal error, project build failed"
    ##teamcity[buildStatus status='FAILURE' ]
}

##teamcity[progressMessage 'Build Passed']
# Good, the build passed
Write-Host "$nl project build passed."  -ForegroundColor Green


##teamcity[progressMessage 'running tests']
# Run the tests.
cmd /c $directorypath\build_tools\nunit\nunit-console.exe $directorypath\Pandell.Tests\bin\debug\Pandell.Tests.dll

# Break if the tests throw an error.
if(! $?) {
    throw "Test run failed."
    ##teamcity[buildStatus status='FAILURE' ]
}

##teamcity[progressMessage 'Tests passed']

私が信じるに足るものから は捕捉されない Throw を実行すると、終了コードとして 1 になりますが、残念ながらTeamCityはそうでないと言っています。

[19:32:20]Test run failed.
[19:32:20]At C:\BuildAgent\work\e903de7564e599c8\build.ps1:44 char:2
[19:32:20]+     throw "Test run failed."
[19:32:20]+     ~~~~~~~~~~~~~~~~~~~~~~~~
[19:32:20]    + CategoryInfo          : OperationStopped: (Test run failed.:String) [],
[19:32:20]   RuntimeException
[19:32:20]    + FullyQualifiedErrorId : Test run failed.
[19:32:20]
[19:32:20]Process exited with code 0
[19:32:20]Publishing internal artifacts
[19:32:20][Publishing internal artifacts] Sending build.finish.properties.gz file
[19:32:20]Build finished

また、重要なことかもしれませんが、私の Execution Mode に設定されていることです。 Execute .ps1 script with "-File" argument .

に変更してみたところ Put script into PowerShell stdin with "-Command -" arguments という終了コードで失敗しました。 1 という終了コードが表示され、テストに合格していても失敗します。私は、これを -File として実行するのが正しい方法になると思います。

にあるスクリプトを開くと C:\BuildAgent\work\e903de7564e599c8\build.ps1 にあるスクリプトを開いて CMD で手動で実行しても、同じことが起こります...。つまり、失敗しているテストは失敗し %errorlevel% はまだ 0 .

それでも、PowerShell で実行して $LASTEXITCODE を呼び出すと、毎回正しいコードが返されます。

どのように解決するのですか?

これはPowerShellの既知の問題です。スクリプトを実行する際に -file を使用してスクリプトを実行すると、終了コード 0 が返されるはずです。

(更新: 以下のリンクはもう機能しません。この問題については PowerShell: ホット (1454 アイデア) - Windows Server )

を使用しているため -command を使ってもうまくいかなかったので、スクリプトの先頭にトラップを追加してみてはいかがでしょうか。

trap
{
    write-output $_
    ##teamcity[buildStatus status='FAILURE' ]
    exit 1
}

上記により、例外が発生した際に適切な終了コードが表示されるはずです。