Workaround for Start-Transcript on native processes

Workaround for Start-Transcript on native processes

  • Comments 5

Introduction

Recently, we came across an interesting bug that had been around for awhile (http://connect.microsoft.com/PowerShell/feedback/ViewFeedback.aspx?FeedbackID=315875). If you do the following:

Start-Transcript
ipconfig
Stop-Transcript

If you look at the transcript, you’ll see that the output of ipconfig was not captured.

Why is this happening?

PowerShell recognizes that ipconfig is a native console application. Since many of these applications do direct writes to the console buffer (i.e. more.com, edit.com etc.), we don’t direct the output handles. Because of that, we can’t capture their output directly. This renders the transcription framework ineffective because the Out-Default cmdlet is unable to capture anything from ipconfig.

How can we work around it?

The workaround is actually quite simple. All you have to do is to pipe the output from ipconfig.exe to Out-Default.

Start-Transcript
ipconfig | Out-Default
Stop-Transcript

Tianjie (James) Wei [MSFT]
Software Design Engineer
Windows PowerShell Team

Leave a Comment
  • Please add 4 and 1 and type the answer here:
  • Post
  • Perhaps in a future version of PowerShell a switch parameter -RedirectNative or something on Start-Transcript could be added as a way for the user to opt in if they will not be using incompatible native applications?

  • Yes, it would be very nice to have some runspace or global setting so that the script did not have to be modified when run from someone's application. In general it would be nice to better support running PowerShell from an application that captures the output. The whole concept of a "screen" is hard to deal with from an application. Nice would be to have a sequential console mode that had no restrictions on linesize or need for screen buffer or addressing.

  • A -tag ABC command line option to ipconfig would help greatly.

    We run many different system utilities, capture their stdout/stderr,errno output and filter that output using powershell/dos text processing tools.  That output is feed to an event filtering system for overall system monitoring.

    Can we get better parsable output from the more popular dos command line utility programs?

    For example, ipconfig /ALL returns hard to parse output if you have more than one DNS server.  The second DNS line has blanks and an IP address.  This is not helpful if you want to do:

    for each line in 'ipconfig /ALL | findstr DNS' do

     { parse line; ping dns server by ip address }

    This is compounded when you want to use 20+ command line utilities, each with different not text search friendly output, and with different behavior on recent versions of windows (from win 7 down to XP and Server 2003).

  • Wanted to share a way to capture all output and handle each stream separately.  Below is a simple script on how you can do this.  I use the job object in PS 2.0 to accomplish this. Note:  this is designed for non-interactive scenarios like scheduled tasks.  I included PowerShell commands and the IPCONFIG which is not a native PowerShell command.  Works like a champ.  In fact, you can actually check the job status and send an e-mail accordingly.  You could include an exception in the body of the e-mail in case the job fails since you have access to the separate error stream.  I guess there is no need for a writing a custom PowerShell host if you want to direct output to different sources.

    $testScript = `

    {

       $VerbosePreference = "Continue"

       $ErrorActionPreference = "Continue"

       $WarningPreference = "Continue"

       $DebugPreference = "Continue"

       Write-Verbose "verbose 1"

       Write-Verbose "verbose 2"

       Write-Verbose "verbose 3"

       Write-Error "an error 1"

       Write-Error "an error 2"

       Write-Error "an error 3"

       Write-Warning "a warning 1"

       Write-Warning "a warning 2"

       Write-Warning "a warning 3"

       Write-Debug "debug string 1"

       Write-Debug "debug string 2"

       Write-Debug "debug string 3"

       Write-Output "output 1"

       Write-Output "output 2"

       Write-Output "output 3"

       "this is output"

       1,2,3

       Get-Process

       ipconfig

    }

    $job = Start-Job -Name "MessageTest" -ScriptBlock $testScript

    Wait-Job -Job $job -TimeOut -1

    foreach ($jobResult in $job.ChildJobs)

    {

     $jobResult.Output | Out-Host | Write-Host

     $jobResult.Verbose | ForEach-Object  -Process {$_.Message | Write-Host}

     $jobResult.Warning | ForEach-Object -Process {$_.Message | Write-Host}

     $jobResult.Debug | ForEach-Object -Process {$_.Message | Write-Host}

     $jobResult.Error | ForEach-Object -Process {$_ | Out-Host | Write-Host}

    }

  • Thanks for the info, much appreciated.

Page 1 of 1 (5 items)