Solving Problems with PowerShell (Part 4)

by Apr 11, 2023

PowerShell offers you a plentitude of approaches to solve a task. They always boil down to the same strategies. In this mini-series, we will illustrate them all one by one.

Here’s the problem to solve: get the MAC address of your computer.

In our previous tips we looked at commands and operators. But what if you still cannot get the information you need?

Even then PowerShell has options for you because you can directly access .NET Framework types and methods. Or put differently: if there was no programmer that did the job for you and provided you with specific commands, you can program the functionality yourself.

Obviously, this can quickly become the most difficult approach because now you need programmer skills and need to google even more. What you need to find is a built-in .NET type that deals with the information you need.

After a bit of research you may discover that the [System.Net.NetworkInformation.NetworkInterface] .NET type manages network adapters, and all .NET types expose their methods in PowerShell when you add two colons:

 
PS C:\> [System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces()


Id                   : {DC7C0CE2-B070-4070-B5CB-1C400DA69AF8}
Name                 : vEthernet (Default Switch)
Description          : Hyper-V Virtual Ethernet Adapter
NetworkInterfaceType : Ethernet
OperationalStatus    : Up
Speed                : 10000000000
IsReceiveOnly        : False
SupportsMulticast    : True

Id                   : {44FE83FC-7565-4B18-AAC8-AB3EC075E822}
Name                 : Ethernet 2
Description          : USB Ethernet
NetworkInterfaceType : Ethernet
OperationalStatus    : Up
Speed                : 1000000000
IsReceiveOnly        : False
SupportsMulticast    : True

...   
 

Since .NET returns structured data, there is no difference between results returned by a PowerShell cmdlet and results returned by a raw .NET method. You can consume and process the data in the same way:

 
PS C:\> [System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() | Select-Object -Property Name, NetworkInterfaceType, Description

Name                         NetworkInterfaceType Description                                                       
----                         -------------------- -----------                                                       
vEthernet (Default Switch)               Ethernet Hyper-V Virtual Ethernet Adapter                                  
Ethernet 2                               Ethernet USB Ethernet                                                      
Local Area Connection* 1            Wireless80211 Microsoft Wi-Fi Direct Virtual Adapter                            
Local Area Connection* 2            Wireless80211 Microsoft Wi-Fi Direct Virtual Adapter #2                         
WLAN                                Wireless80211 Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)
Bluetooth Network Connection             Ethernet Bluetooth Device (Personal Area Network)                          
Loopback Pseudo-Interface 1              Loopback Software Loopback Interface 1    
 

However, the .NET method you found may not directly contain the information you require. In our example, GetAllNetworkInterfaces() returns all network adapters, but to get their MAC addresses, you need to dive deeper into the .NET object tree. That’s what makes this technique harder (but also exciting and rewarding) to use.

Here is the finished .NET code to get all the required information about your network adapter, this time even including the information whether or not a particular adapter is currently up:

[System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() |
  ForEach-Object {
      $nic = $_
      
      [PSCustomObject]@{
          Name = $_.Name
          Status = $_.OperationalStatus
          Mac   = [System.BitConverter]::ToString($nic.GetPhysicalAddress().GetAddressBytes())
          Type = $_.NetworkInterfaceType
          SpeedGb = $(if ($_.Speed -ge 0) { $_.Speed/1000000000 } )
          Description  = $_.Description
      }
  }

This is where the circle closes: by wrapping this raw .NET code into a PowerShell function, you add a new simple command to the PowerShell vocabulary:

function Get-MacAddress
{
    [System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() |
      ForEach-Object {
          $nic = $_
      
          [PSCustomObject]@{
              Name = $_.Name
              Status = $_.OperationalStatus
              Mac   = [System.BitConverter]::ToString($nic.GetPhysicalAddress().GetAddressBytes())
              Type = $_.NetworkInterfaceType
              SpeedGb = $(if ($_.Speed -ge 0) { $_.Speed/1000000000 } )
              Description  = $_.Description
          }
      }
}

Once you run this function definition, you now can again use a highly specialized and easy to use PowerShell command and append your always common set of PowerShell cmdlets (Select-Object, Where-Object) to bring the data into the desired form:

 
PS C:\> Get-MacAddress | Where-Object Mac | Select-Object -Property Name, Status, Mac, SpeedGb

Name                         Status Mac               SpeedGb
----                         ------ ---               -------
vEthernet (Default Switch)       Up 00-15-5D-58-46-A8      10
Ethernet 2                       Up 80-3F-5D-05-58-91       1
Local Area Connection* 1       Down 24-EE-9A-54-1B-E6        
Local Area Connection* 2       Down 26-EE-9A-54-1B-E5        
WLAN                           Down 24-EE-9A-54-1B-E5    0,78
Bluetooth Network Connection   Down 24-EE-9A-54-1B-E9   0,003  
 


Tweet this Tip! Tweet this Tip!