Capture output from command line tools with PowerShell

A simple task and then again not

A customer asked me if it was possible to grab output from a command and analyze the output afterwards.

In the particular case he needs to call a telnet session and check if there was a proper response from the server.

The easy solution and then again not

The very simple solution would be to start the command from PowerShell, redirecting the output to a file, wait for the process to finish and then read the file content.

But in this case the process would not end on its own, as the telnet server would prompt for username and password.

The complex solution and then again not Smile

Having played around with grabbing output from processes using .NET, I knew that the System.Diagnostics.ProcessStartInfo object was able to handle redirecting of output without using files.

In order to keep a handle on the process after starting it, I would use System.Diagnostics.Process, as that object gives you access to the process during runtime and keeps data after the process exits.

So I fired up PowerShell ISE (I simply love that tool) and started typing away.

First we need to setup the ProcessStartInfo object.

Instead of using a telnet command, I just use a simple ping localhost to simulate a command that generates output, I also added the –t switch to make ping run forever.

To kick off the command, we need a Process object that uses the ProcessStartInfo object.

In  some cases the command may exit on its own after doing whatever it does, but in the case of the telnet (and ping with –t) it will not, so we need to handle this, I decided that a 5 second wait would be sufficient in this case. So after waiting for 5 seconds we check to see if the process is still running, if so we just go and kill it.

Now that we are sure that the command is done executing, we can grab the output from stdout and stderr, both are useful when we analyze the output from a command line tool, as some will write only to stdout while others will write normal output to stdout and errors to stderr. Remember to call the method ReadToEnd() and not just assign the value of StandardOutput to your variable. The content from StandardOutput is a stream object that must be read like a file.

Now that we have the output from the command line, we can start to analyze if things went well or not. In the case of Ping we can look for the text “Reply from” to indicate success.

A little note to remember, the $stdout contains an array of strings, and normally $stdout -contains “Reply to” would return true, but for some reason it doesn’t. However calling the array method contains will correctly return true if the array contains the text “Reply to”. I suspect this to be caused by the fact the array is a .NET object but I am not sure of this.

The script simply returns 0 if the Reply from text is found, and 1 if not.

You can download the complete script here

By | 2014-01-16T10:17:02+00:00 January 16th, 2014|Powershell|6 Comments

About the Author:

Ronnie Jakobsen

Twitter: @RonnieJakobsen

6 Comments

  1. Axel Limousin May 22, 2014 at 16:38 - Reply

    Great tips ! Thanks !

  2. Nelson June 8, 2014 at 20:37 - Reply

    Great posting!

    I have a similar problem running a .Net BUILD.

    Here is my code:

    #—————————————————————
    $ProcessStartInfo = New-Object System.Diagnostics.ProcessStartInfo;
    $ProcessStartInfo.Arguments = $BuildArguments;
    $ProcessStartInfo.FileName = $gDevEnv ;
    $ProcessStartInfo.CreateNoWindow = $true
    $ProcessStartInfo.RedirectStandardError = $True;
    $ProcessStartInfo.RedirectStandardOutput = $True;
    $ProcessStartInfo.UseShellExecute = $False;

    $BuildProcess = New-Object System.Diagnostics.Process;
    $BuildProcess.StartInfo = $ProcessStartInfo;

    $BuildProcess.Start() | Out-Null; # ignore return value with Out-Null
    $BuildProcess.WaitForExit();
    $stdout = $BuildProcess.StandardOutput.ReadToEnd();
    if ($stdout.Contains(“0 failed”) -eq $False)
    {
    Write-Output ‘***** Build failed see log ‘ ;
    Exit 1;
    }

    The if statement throws the following error:

    BuildSolutionOrProject : Build Error
    “D:MyProjectFolderMyProject.Net.vdproj”, You cannot call a method on a null-valued expression.
    At D:BuildScriptsTargets.ps1:157 char:6
    + BuildSolutionOrProject $gTFSDiskLocatio $TargetInfo
    etc
    +
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorExcep
    tion
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorExceptio
    n,BuildSolutionOrProject

    The error is in the if ($logBody.Contains(“0 failed”) -eq $False) line.

    Thanks for any help!

    • Ronnie Jakobsen
      Ronnie Jakobsen June 9, 2014 at 13:46 - Reply

      The error you get, indicates that the stdout does not contain any value. You may want to check if the application you run from your code actually uses standard output.

  3. Scott Clegg October 20, 2014 at 18:50 - Reply

    This works great! Thanks for the time to create this tip!

  4. […] Capture output from command line tools with PowerShell – Now that we are sure that the command is done executing, we can grab the output from stdout and stderr, both are useful when we analyze the output from a command line …… […]

  5. Diagg November 17, 2017 at 11:39 - Reply

    I Ronnie, the code is actually flooded with HTML tags can you please repost

Leave A Comment