3

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.

5
  • 1
    Have you looked into the redirection operator learn.microsoft.com/en-us/powershell/module/… Commented Nov 3, 2022 at 19:32
  • *because mobile doesnt want to cooperate. If you’re calling your script from the powershell console you can try adding 2>> $outfile and see if that works for you Commented Nov 3, 2022 at 19:33
  • That's the specific issue, I can't call it from the console in that way, it is sucked in by the .wsb, so it runs in a hidden way. This is desireable, I want it to be silent, but it would be etremely useful to be able to see any errors that may be generated. I would gladly use redirection if possible and do that often with other scripts, but it is not possible here. Commented Nov 3, 2022 at 20:06
  • 1
    like, wrapping all your script in a try block and then in the catch block you capture the error $_ and output it to a file? Commented Nov 3, 2022 at 20:53
  • 1
    Even when running silently there will be information and error channels. Not just a visible console, right? Did you try the redirect options? Then there is always Start-Transcript that will give you everything... Commented Nov 3, 2022 at 20:56

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.