Capturing standard out and error with Start-Process
That's how Start-Process
was designed for some reason. Here's a way to get it without sending to 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
In the code given in the question, I think that reading the ExitCode property of the initiation 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 -PassThru
and -Wait
parameters (this caught me out for a while).
I also had this issue and ended up using Andy's code to create a function to clean things up when multiple commands need to be run.
It'll return stderr, stdout, and exit codes as objects. One thing to note: the function won't accept .\
in the path; full paths must 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"