Scaling WMI with PowerShell and Remoting
Welcome back to our article series on exploring how to use PowerShell and WMI to discover system drive information for servers in your enterprise. As usual with my articles, the end result is not necessarily as important as what you learn along the way. To that end, I want to continue our journey and explore some new territory.
- Part 1: Checking System Drive Spaces with WMI and PowerShell
- Part 2: Getting System Drive Alternatives
- Part 3: Compound Filtering with WMI and PowerShell
- Part 4: Scaling WMI with PowerShell and Remoting
- Part 5: Using PowerShell’s Storage Cmdlets to Query the System Drive
One of the potential drawbacks in my previous attempts was that I needed to run Get-WmiObject twice. When trying to query a lot of computers, Get-WmiObject has to process all of the computers sequentially. I can address both of these issues by using PowerShell remoting. The %systemdrive% variable can also be resolved through the ENV provider. You can easily reference it with $env:systemdrive. Using Invoke-Command, I can quickly determine the value even on remote computers.
This is very fast, and I can integrate this into Get-WmiObject, except I can invoke it remotely.
The tricky part is to remember to wrap $env:systemdrive inside a subexpression. This command took about 614 milliseconds compared to this:
This took about a second and a half. This really takes off is when you're querying multiple computers. I'm going to import my list of computer names:
And as I did before, I'm going to pre-qualify them and filter out those that are offline.
Now, I can use this list of computers with my Invoke-Command expression. I want to use the same scenario, where all I am interested in are those servers with less than 5 GB of free space on the system drive.
This took about 4.65 seconds to process seven computers. The WMI query runs remotely, and then I am sorting and selecting results based on the total objects returned. Although sometimes you can tweak a little performance gain by selecting properties at the source.
This gives me the same result but Select-Object runs remotely, which limits what has to come back to me across the wire. The sorting takes place on my computer. This ran about a second faster. But your results might vary. Part of the processing with Invoke-Command is the setup and tear down of temporary PSSessions to the remote computers. If you think you will be using remote connections more than once, then you can setup persistent sessions.
And by persistent I mean for as long as your PowerShell session is running. By the way this took 2.3 seconds to create seven connections. The Invoke-Command expression changes from –Computername to –Session.
The results are the same but this took less than a second to complete. If you are querying a lot of computers, you don't have to worry about overwhelming your network. By default Invoke-Command will throttle connections to 32 at a time. So if you were querying 100 computers, PowerShell would kick off 32 connections, and then as the command finished start the next one from the queue. You can control the size of the queue with the –ThrottleLimit parameter. This is just something you'll need to experiment with. Because I only have seven sessions, PowerShell will query all of them at once. In this example, I experimented with a throttle limit of four.
I got the same results, but this time it only took 125 milliseconds. Frankly, I was a bit surprised, but pleasantly so, and it tells me that I need to pay more attention to this parameter in the future. By the way, if you are finished with the sessions and want to clean them up, all you have to run is this:
As you've seen using WMI is pretty simple once you've resolved the system drive. But WMI is not the only solution. Next time we'll look at some new commands that solve our challenge.