Redirect standard output from a external program to PowerShell


Sometimes when developing tools and scripts you need to use external applications to take care of a task, most applications come with a CLI so you can also use them from the command line and integrate them into your own scripts, however you may need to get the output of that application into your own script to know whether a task has been successful.

In PowerShell you can start a process and redirect the output of the process back to your application through the use of events that trigger when output is received, we can also redirect any error output back to your application as well so you can take action if an error occurs.

I will walk you through an example of this using ping in Windows, ping is a network diagnostics tool built into windows and often called from the command prompt, but ping is actually its own application located in the Windows System32 directory.

To make this work we need to use a Class built into the .NET framework called System.Diagnostics


Capture output from external program in PowerShell

The following step by step example demonstrates how to capture output from another program in PowerShell, here we will start the ping process with an IP address supplied as an argument, an when data is received we will write the data to the PowerShell Console.

  1. The first thing we need to do is create a new object that contains the process information, the process that we want to start and any arguments or parameters.
    # Setup redirection
    $StartInfo = New-Object System.Diagnostics.ProcessStartInfo -Property @{
                    FileName = "$env:SystemRoot\System32\ping.exe"
                    Arguments = "127.0.0.1"
                    UseShellExecute = $false
                    RedirectStandardOutput = $true    #If true redirects standard output from the application
                    RedirectStandardError = $true    #If true redirects error output from the application
                    CreateNoWindow = $true    #Should the process create its own window? Or should it be hidden?
                }
  2. Next we create a new process object and set the StartInfo to our StartInfo object, this process object will manage the actual process we want to run.
    $Process = New-Object System.Diagnostics.Process
    $Process.StartInfo = $StartInfo
  3. Next we register a new event that will trigger when new data is received from the application, here I have added a filter to only write to the console if the data we receive contains "Reply from" indicating we received a reply from our ping.
    # Register Object Events to Receive Output
    $OutEvent = Register-ObjectEvent -Action {
        if($Event.SourceEventArgs.Data -like "Reply from*"){
            Write-Host "New Data" -ForegroundColor Cyan
            Write-Host $Event.SourceEventArgs.Data
        }
    } -InputObject $Process -EventName OutputDataReceived
  4. If you would also like to receive any error output from the external application you can register an error event to capture this.
    $ErrEvent = Register-ObjectEvent -Action {
        if($Event.SourceEventArgs.Data -ne $null){
            Write-Host "Error" -ForegroundColor Red
            Write-Host $Event.SourceEventArgs.Data
        }
    } -InputObject $Process -EventName ErrorDataReceived
  5. Finally we need to register an event for when the external application is closed, you may add additional logic in these functions, in the exit event we need to unregister the events as they are no longer in use.
    $ExitEvent = Register-ObjectEvent -Action {
        Write-Host "Finished"   
        # Unregister events
        $OutEvent.Name, $ExitEvent.Name, $ErrEvent.Name |
            ForEach-Object {Unregister-Event -SourceIdentifier $_}
    } -InputObject $Process -EventName Exited
  6. Now that all the logic is complete, we can start the process and redirect the application output back to our PowerShell script.
    # Start process
    if($Process.Start()){
        # Begin output redirection
        $Process.BeginOutputReadLine()
        $Process.BeginErrorReadLine()
    }
  7. Now if you run this in the PowerShell ISE, you should see that when replies are received from the pings, the events trigger and write output to the console.


Download the full code:



Was this helpful?

Yes No


Comments