PowerShell Performance for Network Adapter Enumeration

2017-12-08T14:27:40+00:00 December 10th, 2014|PowerShell|

As always with Microsoft technologies, there is generally many ways to achieve a common goal. But something that is often overlooked is how quickly you get to that goal. Ok, it’s fair enough that if you’re just running something once or doing anything really lightweight, this probably won’t be a useful read… However, if you’re in the habit of automating things or seeing your code “hang” for noticeable periods of time, then you really should be looking to optimise your work!

In this post, I wanted to quickly explore three options (there are of course many other options) to enumerate all network adapters on the local machine that report the NetConnectionStatus equals “2” and the AdapterType equals “Ethernet 802.3”. For a more fair comparison, the first two options will use the WMI Win32_NetworkAdapter class.

Option 1:

Get-WMIObject Win32_NetworkAdapter -Filter "NetConnectionStatus = 2 AND AdapterType = 'Ethernet 802.3'"

Option 2:

Get-WMIObject Win32_NetworkAdapter | where-object { ($_.NetConnectionStatus = "2") -and ($_.AdapterType -eq "Ethernet 802.3") }

As you can see, in Option 1, the WMI query handles the full filtering. Whereas in Option 2, I split the filtering into a PowerShell “Where-Object”. As you might fully expect, Option 1 is quicker because we’re not jumping into what is effectively a nested loop. By wrapping those cmdlets into a “Measure-Command” block, I got the following results:

  • Option 1: TotalMilliseconds = 299.0157
  • Option 2: TotalMilliseconds = 614.9457

Ok, so why would you pick Option 2? Well, the limitations of WMI for a start. Also, you can handle things much better in PowerShell once you’ve passed things down the pipeline.

Of course, an even faster way would be the lovely new VpnClient module that ships with Windows 8.1 and Server 2012 R2.

Option 3:

Get-NetAdapter | Where-Object { ($_.MediaConnectionState -eq "Connected") -and ($_.MediaType -eq "802.3") }

Again, wrap that in a “Measure-Command” block and we get a staggeringly impressive result by comparison:

  • Option 3: TotalMilliseconds = 19.2925

Before you ask, I’m sorry but even if you install .NET Framework 4.5.1 and Windows Management Framework 4.0 on lower versions of Windows, the VpnClient module is still not available. Yeah ok, it’s easy enough to fudge the modules and dependant namespaces in, but you’re on your own if you do that! The reason for this is that the newer CDXML-based modules are produced by taking a CIM class and sticking some XML around it, then saved as the .cdxml file. Once done, it can be published as a PowerShell module. CIM classes will not be made available to down-level systems earlier than Windows 8 / 2012, so don’t expect to find that functionality.