Another Way to Get Output From a PowerShell Runspace

Most of you who work with runspaces in PowerShell are familiar with the most common way to pull out data that is waiting in another runspace by simply calling Invoke() on the PowerShell instance or using EndInvoke(<handle>) to stop one that is running in the background. Doing either of these will instantly bring back the output that is waiting on the end of that runspace.

image

There is actually yet another way to kick off a runspace in the background and then get the data back without having to call the EndInvoke() method in the PowerShell instance if you are running these asynchronously. It requires just a little bit more work to build out an object to support this but provides the data that you are expecting. Of course, you still need to properly dispose of your runspace when you are done to prevent potential memory leaks from occurring in your console/ISE.

To highlight which one I will be using with BeginInvoke(), you can find it in the image below and I will explain the process after the image.

image

To do this we will begin setting up our runspace in the usual manner by creating the PowerShell instance and adding a script that will run to create an object within it.

$PowerShell = [powershell]::Create()
[void]$PowerShell.AddScript({
    [pscustomobject]@{
        Test = 'test'
    }
})

Ok, nothing really new here yet, but now we need to build a System.Management.Automation.PSDataCollection[T] object that will be used both as an input object but also an output object as shown in the method overloads. The TInput is merely saying that we need to provide some sort of object type that goes with the PSDataCollection object that is being built in which this type of collection is called a generic collection as it is strongly typed and will only allow use to store types that are specified to this collection. Now that we have covered that topic, let’s build this out.

$Object = New-Object 'System.Management.Automation.PSDataCollection[psobject]'

image

All that we have left to do now is to call BeginInvoke() and supplying this object twice as the Input/Output and then after the command has finished, check out the results.

$Handle = $PowerShell.BeginInvoke($Object,$Object)

Instead of calling EndInvoke(), I can just view the $Object variable instead and see the output.

image

As I mentioned earlier, even though I have my results, I still need to clean up after myself by disposing of the PowerShell instance that will then close down the runspace.

$PowerShell.Dispose()

And like that, I have another way to gather my data from a runspace!

About Boe Prox

Microsoft Cloud and Datacenter MVP working as a SQL DBA.
This entry was posted in powershell and tagged , , . Bookmark the permalink.

3 Responses to Another Way to Get Output From a PowerShell Runspace

  1. Pingback: Yet Another Way to Get Output from a Runspace, Reflection Edition | Learn Powershell | Achieve More

  2. Øyvind Kallstad says:

    Nice one Boe! As is often the case reading your posts, I learned something new, and I love learning new stuff! 🙂 Keep up the good stuff, and geek on 😉

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s