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
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).
- 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
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 usebreak
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 atry
statement may abort execution prematurely. - Use of a
trap
statement withoutbreak
may 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-Transcript
won't be a problem, and ensures side effect-free logging - albeit invariably including all of the script's output, as noted.