Capturing Standard Errors and Errors with Start-Process

Is there an error in the PowerShell Start-Process command when accessing the StandardError and StandardOutput properties?

If I run the following, I do not get the output:

 $process = Start-Process -FilePath ping -ArgumentList localhost -NoNewWindow -PassThru -Wait $process.StandardOutput $process.StandardError 

But if I redirect the output to a file, I get the expected result:

 $process = Start-Process -FilePath ping -ArgumentList localhost -NoNewWindow -PassThru -Wait -RedirectStandardOutput stdout.txt -RedirectStandardError stderr.txt 
+88
powershell start-process
Jan 06 2018-12-12T00:
source share
7 answers

This is why Start-Process was developed by Start-Process . Here is a way to get it without sending to a file:

 $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = "ping.exe" $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.Arguments = "localhost" $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null $p.WaitForExit() $stdout = $p.StandardOutput.ReadToEnd() $stderr = $p.StandardError.ReadToEnd() Write-Host "stdout: $stdout" Write-Host "stderr: $stderr" Write-Host "exit code: " + $p.ExitCode 
+111
Jan 06 '12 at 17:43
source share

In the code provided in the question, I think reading the ExitCode property of the initialization variable should work.

 $process = Start-Process -FilePath ping -ArgumentList localhost -NoNewWindow -PassThru -Wait $process.ExitCode 

Note that (as in your example) you need to add the parameters -PassThru and -Wait (this is me -Wait ).

+16
Dec 11 '14 at 10:19
source share

I also had this problem, and I ended up using Andy code to create a function to clean up when I need to execute a few commands.

It will return stderr, stdout and exit codes as objects. It is worth noting: the function does not accept .\ On the way; full paths should be used.

 Function Execute-Command ($commandTitle, $commandPath, $commandArguments) { $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = $commandPath $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.Arguments = $commandArguments $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null $p.WaitForExit() [pscustomobject]@{ commandTitle = $commandTitle stdout = $p.StandardOutput.ReadToEnd() stderr = $p.StandardError.ReadToEnd() ExitCode = $p.ExitCode } } 

Here's how to use it:

 $DisableACMonitorTimeOut = Execute-Command -commandTitle "Disable Monitor Timeout" -commandPath "C:\Windows\System32\powercfg.exe" -commandArguments " -x monitor-timeout-ac 0" 
+11
Nov 11 '15 at 14:32
source share

I really had problems with these examples from Andy Arismendi and from LPG . You should always use:

 $stdout = $p.StandardOutput.ReadToEnd() 

before the call

 $p.WaitForExit() 

Full example:

 $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = "ping.exe" $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.Arguments = "localhost" $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null $stdout = $p.StandardOutput.ReadToEnd() $stderr = $p.StandardError.ReadToEnd() $p.WaitForExit() Write-Host "stdout: $stdout" Write-Host "stderr: $stderr" Write-Host "exit code: " + $p.ExitCode 
+6
Jun 20 '16 at 15:34
source share

IMPORTANT:

We used the function as above LPG .

However, it contains an error that you may encounter when starting a process that generates a lot of output. Because of this, you may get a dead end when using this function. Instead, use the adapted version below:

 Function Execute-Command ($commandTitle, $commandPath, $commandArguments) { Try { $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = $commandPath $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.Arguments = $commandArguments $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null [pscustomobject]@{ commandTitle = $commandTitle stdout = $p.StandardOutput.ReadToEnd() stderr = $p.StandardError.ReadToEnd() ExitCode = $p.ExitCode } $p.WaitForExit() } Catch { exit } } 

Additional information on this subject can be found on MSDN :

A deadlock condition may occur if the parent process calls p.WaitForExit before p.StandardError.ReadToEnd and the child process writes enough text to fill the redirected stream. The parent process will wait indefinitely for the child process to complete. The child process will wait indefinitely while the parent reads the full StandardError stream.

+5
Mar 24 '17 at 9:05
source share

Here is my version of a function that returns the standard System.Diagnostics.Process with 3 new properties

 Function Execute-Command ($commandTitle, $commandPath, $commandArguments) { Try { $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = $commandPath $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.WindowStyle = 'Hidden' $pinfo.CreateNoWindow = $True $pinfo.Arguments = $commandArguments $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null $stdout = $p.StandardOutput.ReadToEnd() $stderr = $p.StandardError.ReadToEnd() $p.WaitForExit() $p | Add-Member "commandTitle" $commandTitle $p | Add-Member "stdout" $stdout $p | Add-Member "stderr" $stderr } Catch { } $p } 
0
Aug 01 '18 at 10:07 on
source share

Here's a tricky way to get the output of another powershell process:

 start-process -wait -nonewwindow powershell 'ps | Export-Clixml out.xml'; import-clixml out.xml 
0
Jul 11 '19 at 13:55 on
source share



All Articles