Effective PowerShell Item 14: Capturing All Output from a Script

Both version 1 and version 2 of Windows PowerShell have a nasty limitation when it comes to capturing *all* output from a script.  First up, within a script there is no way to redirect host (Write-Host), verbose, warning and debug message to a log file.  There is a mechanism within PowerShell that allows you to capture these streams of information – Start-Transcript.  At first blush, this seems promising however the wheels fall off pretty quickly primarily because Start-Transcript doesn’t capture the output of EXEs.  So all that output from compilers, build tools, etc doesn’t get captured.  That’s a huge, gaping hole.  Furthermore, Start-Transcript is really aimed at capturing your entire PowerShell session.  It isn’t particularly suited for script logging.  For instance, some folks including myself use Start-Transcript in their profile to capture an entire PowerShell session.  This is very handy when you need to look up how you did something previously which is possible because you can search your transcript files.  However, if you start a script that blindly calls Start-Transcript it will error.  You can only call Start-Transcript if it hasn’t already been started . There is no notion of nested transcripts.

If you find these limitations as annoying as I do, please vote on them via the Microsoft Connect site:

https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=283088&SiteID=99
https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=297055&SiteID=99

For now, the best way to accomplish this is to use a host that can capture all PowerShell output.  It turns out that executing the script through another instance of PowerShell.exe will allow you to capture all the output.  For instance, consider the following script (test.ps1) that exercises the various output streams:

 1: $DebugPreference = 2
 2: $VerbosePreference = 2
 3: $WarningPreference = 2
 4:
 5: hostname.exe
 6: Write-Host "host"
 7: Write-Output "output"
 8: Write-Error "error"
 9: Write-Verbose "verbose"
 10: Write-Warning "warning"
 11: Write-Debug "debug"

If you run the following you can easily capture all PowerShell output as shown below:

PS> powershell.exe -noprofile -file test.ps1 > test.log
PS> Get-Content test.log
HILLR1
host 
output 
C:\Users\hillr\Bin\test.ps1 : error
  + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
 + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,test.ps1 host
VERBOSE: verbose
WARNING: warning
DEBUG: debug

Updated 3/7/09: Aleksandar pointed out that you can just use Powershell.exe.  No need to go through cmd.exe.  Thanks!

psmdtag:script – Logging output

Advertisements
This entry was posted in Effective PowerShell. Bookmark the permalink.

11 Responses to Effective PowerShell Item 14: Capturing All Output from a Script

  1. Eric says:

    Thanks for this! I’m fairly inexperienced with PowerShell. I’ve used it infrequently in the past. Using what I learned from your blog, I was able to figure out a problem that I’d been having when I was launching my script from the standard Windows command prompt.

  2. Pingback: Piping powershell messages to Write-EventLog - Admins Goodies

  3. Mario says:

    the write-error output does not show up in my test.log

  4. Mario says:

    I have to correct myself. it works during a PS Session. I’d like to make a shortcut that runs test.ps1 and logs to test.log. Any Ideas?

  5. Mario says:

    cmd.exe /c powershell.exe -file test.ps1 > test.log
    Does not work with UNC paths though.

    Actually I need something like teeing. Want the Output on the Screen and in the logfile. And all this started by a shortcut.

  6. kiquenet says:

    Hi mister,

    I use Powershell remoting, and I would like log to file (any few messages, the rest to output console)

    Which is the better manner for log to a file using powershell?

    Maybe Andy Arismendi: http://poshcode.org/3270

    Suggestions? thanks

  7. Andrei says:

    I recently had the same problem with logging all commands to a file.
    Solution and code snippet is here: http://www.rubaniuk.com/?p=113

  8. Pingback: Powershell notes. Part 1 | Automate IT!

  9. Pingback: Capturing the String Output of Get-CsPoolFabricState on Lync Server | Tom Talks UC

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s