Reputation: 21204
We're using the following statement to enable TeamCity to recognize errors in our PowerShell deployment scripts:
trap { $host.SetShouldExit(1) }
This works fine, however, since Param(...) needs to be the very first statement we have to use this order:
Param(
...
)
Set-StrictMode -Version 2.0
$ErrorActionPreference = "Stop"
trap { $host.SetShouldExit(1) }
Is there any way to also trap errors during the Param() evaluation? E.g. if we omit a mandatory parameter, TeamCity is not able to detect this at the moment.
Upvotes: 2
Views: 4513
Reputation: 762
Actually I had the same question and ended up on combining both approaches:
-Command
calling to powershell.exe
to allow to trap the Parameter errortrap
within the Powershell script to handle errors within - and use $LASTEXITCODE
to counter balance Powershell's behaviorCalling side in BAT
/CMD
:
@echo off
powershell -NoLogo -NonInteractive -Command "& {trap {Write-Error $_; exit 2}; scipt.ps1 %1 %2 %3 %4 %5 %6 %7 %8 %9 ; exit $LASTEXITCODE}"
IF %ERRORLEVEL% NEQ 0 Exit /B %ERRORLEVEL%
Goto :EOF
:EOF
The PowerShell script
Param(
...
)
Set-StrictMode -Version 2.0
$ErrorActionPreference = "Stop"
trap { Exit(1) }
...
That way one can decide between Param
errors (exit code 2
) and errors in the script itself (exit code 1
)
Upvotes: 1
Reputation: 431
This is yet another annoying oversight of Powershell. I find the best way to workaround this Powershell bug is to roll your own mandatory verification. It's more code, but clear, simple and fail-safe.
First remove the mandatory flag from the param declaration and check for null or empty at the beginning of the script.
param (
[string] $required_param
)
# Check required params
if ([string]::IsNullOrEmpty($required_param)) {
Write-Host "The required_param is required."
exit 1;
}
Plus you can call your script with the regular File argument:
powershell -File foo.ps1
Hope this helps.
Upvotes: 4
Reputation: 201692
Try putting the trap in the TeamCity string to execute. For instance, say I have a script with a param block at the top of the script (foo.ps1) with a mandatory parameter that I don't supply e.g.:
param([Parameter(Mandatory)][int]$num, [bool]$bool)
Then I can execute it like so from CMD and get an error exit code:
C:\> cmd /c Powershell.exe -NonInteractive -Command "& {trap {exit 1}; c:\foo.ps1}"
C:\> %ERRORLEVEL%
1
BTW you might find this blog post an interesting read.
Upvotes: 1
Reputation: 13473
If I understand you correctly, you want to execute a PowerShell script, and have TeamCity see the error returned. I think that this is very similar to how I catch and return errors in my scripts that need to be run with scheduled tasks.
How I do it is first make functions/cmdlts for everything you want to do. Then execute those functions in a try..catch block. e.g.
#My test function
Function test{
Param( [Parameter(Mandatory=$true)] [int]$a )
Process
{
Write-Host "Hi $a"
}
}
#Execute Function
Try{
test 1234 -ErrorAction "Stop"
}
Catch
{
#Error encountered
Write-Host "Error Encountered: exiting"
#Return Bad error code
Exit 1
}
This should catch any parameters that are incorrect.
This may not be applicable, but other people's reference, for scheduled tasks, I run my scheduled tasks with the following command:
powershell.exe -Command ". C:\Scripts\Run_PS1.ps1 ; exit $LASTEXITCODE"
This will run powershell, execute the script, and then correctly return the last exit code back to the scheduled task.
Hope this helps you out.
Upvotes: 0