Grunt | Throw Compilation Error to Powershell - powershell

I am trying to call Grunt command from my powershell script. But in case of any complilation failure Grunt is printing the error code to the console but not returning anything to powershell command line and even not going to catch block.
Please let me know how to resolve this issue.

Noah's answer (using $ErrorActionPreference) can work. Alternatively you can use the automatic variables $? and/or $LastExitCode immediately after executing the external command to take a specific action if it failed. This doesn't require a try-catch block For example:
Grunt.exe -whatever
if (!$?) { throw "Grunt command returned $LastExitCode" }

Without seeing a screenshot of what is happening or more details it is hard to say what is going on here. However, the basics of PS are that you need to make sure the error is considered terminating for the catch block to trigger. Since this does not sound like a native PS cmdlet you can force it to be a terminating error like below:
Try {
$ErrorActionPreference = 'Stop'
Grunt.exe whatever
$ErrorActionPreference = 'Continue'
}
Catch {stuff}

Related

PowerShell, tell a script to output all errors to a text file

I have a PowerShell script that is the startup script for Windows Sandbox and so it runs silently.
Is it possible to put some kind of declaration within a PowerShell script, say at the start of the script, that tells the silently running script to output all of its errors to a text file?
Edit (for Fitzgery's comment): it is not possible for me to use redirection for the script because it is running silently as part of the Windows Sandbox startup. I would like something within the script itself to instruct the running script to output all errors to a text file.
Try the following, which relies on the fact that all errors that occur in a session get recorded in the automatic $Error variable:
$Error.Clear() # Reset the session's error log so far
try {
# ... your script
} finally {
# Save all errors that occurred in this script to a file.
$Error > errors.txt
}
Caveat:
The use of a try statement has a side effect:
Your script may terminate prematurely, because any normally only statement-terminating error becomes a script-terminating error and therefore instantly triggers the finally clause; that said, statement-terminating errors aren't common, and it's arguably better to abort execution when they occur (unanticipated).
If you were to omit the try statement and simply placed $Error > errors.txt at the end of your script, (non-terminating and) statement-terminating errors would be handled as usual, but the $Error > errors.txt statement would never get to execute if a script-terminating error occurred.
An alternative solution using trap is side effect-free only if you know your script not to produce script-terminating errors:
Script-terminating errors are those explicitly created with throw, or implicitly via -ErrorAction Stop or $ErrorActionPreference = 'Stop'
The (rarely used anymore) trap
statement allows you to act on errors without stopping execution, namely if you do not use break in the script block you pass to it.
While it therefore continues after non-terminating and statement-terminating errors, as during normal execution, it also continues after script-terminating ones.
Therefore, the side effect - if you script does create script-terminating errors, is that it may not stop your script when you expect it to.
# Create or truncate the target file.
$errLogFile = New-Item errors.txt -Force
# Traps all errors and logs them in the target ffile.
# Note:
# * Using neither `break` or `continue` in the script block
# still also prints the error and continues execution.
# * CAVEAT: Even *script*-terminating errors then
# do NOT abort execution.
trap { $_ >> $errLogFile }
# ... your script
Use of Start-Transcript:
Start-Transcript is an way to capture all of a script's output, not just errors (that is, output from all of PowerShell's output streams is logged, notably including success output (data) - you get no choice).
It must be paired with Stop-Transcript to close the transcript file.
If you neglect to call Stop-Transcript, the transcript stays open and continues logging for the remainder of the session.
In order to ensure that Stop-Transcript is called, you're faced with the same tradeoffs as above:
Calling it in the finally block of a try statement may abort execution prematurely.
Use of a trap statement without break may not stop execution when it should.
That said, if the execution of your script is the only thing happens in your session - such as in a CLI call with -File - not calling Stop-Transcript won't be a problem, and ensures side effect-free logging - albeit invariably including all of the script's output, as noted.

How can I propagate the failure to the caller from an invoked script in powershell

I am using jenkins to drive a powershell script. The script is build.ps1. In the Jenkins pipeline I specify
powershell './build.ps1'
I also tried
powershell './build.ps1; exit $LastExitCode'
I have a typo in my build.ps1, or I also get build failures, but Jenkins marks it as success anyway. The reason is that errors are apparently not propagated from the build.ps1 execution to the powershell spawned by jenkins. $LastExitCode is always zero. I verified this in a regular PS prompt with a broken script
./broken.ps1; echo $LastExitCode
gives zero even if test.ps1 throws an error.
I also tried to invoke with &. Same effect.
Try adding the following to your Build.ps1
$ErrorActionPreference = 'Stop'
#
# YOUR CODE
#
trap{
echo "Error while building, error: $($Error[0] | select *)"
exit 1
}
That should trap all errors, and exit with an error code 1.
Also if you can add a screenshot of your Jenkins config when you call the script, just to be sure I think it is what it is.
Hope it helps, good luck.

Powershell conditionals

I would like to write this in powershell but can not seem to get it to work no matter how I try it. I've used "try and catch" but it doesn't seem to work the way I want.
Try
{
write-host Attempting Reset
CD C:\MKC1_ECU_Reuse
./power_on.bat
CD C:\UTIL\XDL\XMIT\BIN
.\xpc32_nodriver conm2.xpc -con
.\xpc32_nodriver $global:path\$global:customer\$global:customer_reset.xpc
}
Catch
{
Write-warning "Something went wrong!: $_"
return # script failed
}
In Batch, it would look like this:
Do some task || goto :error
goto :finished
Powershell will try to do the task and then go to the next line regardless of if the task completed successfully. The task I am trying to do is to connect to an EEPROM and write to it. If the write fails, I do not want to continue my script. I would rather be able to display an error telling the operator that there was an issue. I am working with what my company allows me to work with or I would use the newest Powershell that allows for || and &&. Any help would be appreciative.
Inside the batch file you may need something like:
IF %ERRORLEVEL% NEQ 0 (
exit %ERRORLEVEL%
)
That should relay the elevated exit code back to PowerShell in the $LASTEXITCODE variable. Then you may be able to use the logic from the previous answer.
I guess they are forcing you to use .bat, but it might be better is you launched the underlying program from inside PowerShell.
Try/Catch only works with teminating powershell command errors. You can test
if ($LASTEXITCODE -ne 0) or if (-not $?) for an error.
Taking a guess at an answer:
$result = .\xpc32_nodriver $global:path\$global:customer\$global:customer_reset.xpc
if ($result -like '*error*') {
write-warning 'Something went wrong!'
exit 1
}

Find whether PowerShell error is originally Terminating or non-terminating

Lets say I ran a command with ErrorAction Stop and it generated an error. I would like to know whether the error was originally terminating or not?
I have the ErrorVariable or $Error object. Does ErrorVariable catches both kind of errors? I am looking for a property in .NET/PowerShell object which could tell me that this Error was terminating. Are exceptions generated for Non-Terminating errors too?
Plus, when I am writing a command on console (not ISE and not running a script, just single command on console), how can I suppress the Error using ErrorAction variable? Basically, there should not be any red output on the screen.
about_Try_Catch_Finally and about_Trap have some helpful information.
By default non terminating errors aren't caught by try catch but they will show up in $error. You can use -ErrorVariable to define another error variable (about_CommongParameter. So you could use a custom variable for a check for non terminating errors which might make your code easier readable.
By using SilentlyContinue the output is suppressed but the error is still recorded in the error variable.

Can you redirect errors in a powershell script when $ErrorActionPreference is set to stop?

I have some powershell scripts with the following in them:
$ErrorActionPreference = "stop"
trap { Write-Error $_.Exception; }
When calling the script from a powershell window using a powershell redirection operator:
c:\somescript.ps1 2> c:\error.txt
It will only print out the error to the powershell window and not redirect it to the file. If I remove $ErrorActionPreference = "stop" from the script, then the redirection works, but that isn't a viable option since we need the scripts to terminate if it runs into any error. I've tried using '*>' too, but that produces the same results.
Is there any way to redirect the errors to a file without having to change all the scripts?
The problem with your approach is that $ErrorActionPreference = "Stop":
instantly stops (aborts) the entire script and the command that calls it, c:\somescript.ps1 2> c:\error.txt,
which means that the redirection 2> c:\error.txt is not performed, and the error message displays in the console rather than being captured in the specified file.
The workaround is somewhat cumbersome:
Wrap the invocation of the other script in a try ... catch statement as follows:Tip of the hat to FatalBulletHit for his help.
$ErrorActionPreference = 'Stop'
try {
c:\somescript.ps1
} catch {
# Now you can write the error record to the file.
$_ > c:\error.txt
# == Optional additional actions.
# If desired, you can additionally
# emit the error too (write it the error to the error stream).
# !! -ErrorAction Continue is necessary in order to override
# !! $ErrorActionPreference = 'Stop'.
# !! Without it, the use of Write-Error itself would cause an - uncaught -
# !! script-terminating (fatal) error.
Write-Error -ErrorRecord $_ -ErrorAction Continue
# Exit the script with a nonzero exit code to signal failure
# (which is useful if your script is called from *outside*
# PowerShell).
exit 1
}
The need to use -ErrorAction Continue (or temporarily set $ErrorActionPreference = 'Continue') before calling Write-Error in the catch block to avoid causing a script-terminating (fatal) error is surprising; it would also apply if your script / function is an advanced one and you used $PSCmdlet.WriteError($_) instead.
You might want to have a look at using Try Catch Finally for Error Trapping.
I have had the most success with that.
Great TechNet Blog on this subject