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.
CodePudding user response:
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
trystatement 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
finallyclause; that said, statement-terminating errors aren't common, and it's arguably better to abort execution when they occur (unanticipated).
- Your script may terminate prematurely, because any normally only statement-terminating error becomes a script-terminating error and therefore instantly triggers the
If you were to omit the
trystatement and simply placed$Error > errors.txtat the end of your script, (non-terminating and) statement-terminating errors would be handled as usual, but the$Error > errors.txtstatement 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 Stopor$ErrorActionPreference = 'Stop'The (rarely used anymore)
trapstatement allows you to act on errors without stopping execution, namely if you do not usebreakin 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-Transcriptis 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-Transcriptto 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-Transcriptis called, you're faced with the same tradeoffs as above:- Calling it in the
finallyblock of atrystatement may abort execution prematurely. - Use of a
trapstatement withoutbreakmay not stop execution when it should.
- Calling it in the
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 callingStop-Transcriptwon't be a problem, and ensures side effect-free logging - albeit invariably including all of the script's output, as noted.
