'Is it possible to have -RedirectStandardOutput in Start-Process but still display it in the console?

My problem is that I want to Start-Process a powershell file, execute.ps1, that would execute several sql commands then log the outputs in a text file. So far, all the other approaches like start-transcript or *>> just writes the console outputs but not the sql PRINTS. The only thing currently working is -RedirectStandardOutput.

Start-Process powershell "& .\execute.ps1 -dbserver $server -databasename $database -client $client" -RedirectStandardOutput ".\output\$client.txt

However, when I use this, it redirects everything to the txt file leaving the powershell console blank.

Is it possible to display it both in the console and the txt file?



Solution 1:[1]

No. However...

Using ForEach-Object to write output to console and append to a file

You may be able to work around it with a Foreach-Object loop if the sole reason you are redirecting output is to drop it in a file for later processing. However, you won't be able to use Start-Process to control the location of the output:

Note: $_.Trim() is required to prevent additional newlines in Windows PowerShell 5.1 from being output to the file. .Trim() should not be needed as of at least 7.2.3.

You could also opt for Tee-Object to replace the two-line block with a one-line block, however, you lose control over the encoding as Tee-Object does not allow you to set this for its output file.

# Example command: ping
ping google.com | ForEach-Object {
  $_.Trim() | Out-File -Encoding UTF8 -Append .\testping.txt
  $_
}

If you need to use Start-Process however, for example:

  • You need to run a GUI application and block until it completes
  • You are launching an elevated process
  • You are launching a process as another user

Then you are out of luck. Start-Process only allows you to redirect input and output streams from and to files, respectively.


Using [Process]::Start to display output as the program runs while redirecting

There is a solution to be had if you call [Process]::Start(StartInfo) yourself, but this is going to be the most advanced solution, and have the most code involved. But, if you find that you need Start-Process and also want the output to be displayed as the program runs, and not just once the child process ends, I would invite you to take a look at this question of mine. The question is ultimately looking to process lines of output asynchronously using process object started with [Process]::Start(StartInfo).

Rather than reiterate those solutions here, the answers I would direct you to focus on are @mklement0's and @HAL9256's, although @Cpt.Whale's answer using Start-Job and
Receive-Job might work for your needs as well if you don't need to process each line as they are written. In your case, "processing the output asynchronously" just means you want to output the line of output to the Success stream, then append the line to your output file (as shown in the earlier ForEach-Object loop example).


If displaying the output can wait until the child process completes

If you don't care that the program emits its output until after it finishes running, you can look at my synchronous implementation in my other question itself which should simplify things a bit.

Even more simply, use Start-Process -Wait -RedirectStandardOutput FILE and run
Get-Content against the RedirectStandardOutput file path you chose once the process is done executing.


Making errors output a different color

Regardless of how you launch the process and perform STDOUT/STDERR redirection, if you want the error information to be in a different color, just read from the error text and use Write-Host to change the color:

# $errorStream will need to first be populated from [Process].StandardError
# or Get-Content $pathToStandardErrorFile, depending on the technique used
$errorStream | Write-Host -ForegroundColor Red

Keep in mind that this in no way retains the original color information. However, it will write anything that was written to STDERR in Red (or any other color you choose). That said, also keep in mind that not all programs use STDERR for error information. Some use STDOUT to emit error information (perhaps erroneously), and others may use STDERR for other information such as verbose, debug, or trace output.

There isn't a one-size-fits-all workaround here, since programs are not required to (and may have good reason not to in some cases) adhere to standards and best practices.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1