Behind the PowerShell Pipeline logo

Behind the PowerShell Pipeline

Subscribe
Archives
November 8, 2024

Tool Time - WiFi Info

I want to continue the introduction of a new set of PowerShell tools I've been working on. Today's tool was developed to solve a problem I had, although the solution may be useful to others. However, the reason I share this is that I want to share the process I used because that may be of more value to you than the tool itself.

The Problem

My family has a lake cabin that we often visit. I have a NAS device at the lake, as well as one at home. The NAS devices synchronize so I have the same shared folders, like Backup, at both locations. When I am at the lake with my laptop, I want it to map PSDrives to the NAS at the lake. When I am at home, I want it to map PSDrives to the NAS at home. I don't want to rely solely on the IP Address because it is possible that I'll connect to a network while traveling that uses the same private address space.

I need to get WiFi connection information to determine if I am at the lake or at home. Unfortunately, even though there are PowerShell cmdlets that provide network adapter information, as far as I can tell, there's nothing that will tell me what WiFi network I am connected to.

Using netsh

Fortunately, I can get this information using the old-school netsh command.

PS C:\> netsh wlan show interfaces

There is 1 interface on the system:

    Name                   : Wi-Fi
    Description            : Intel(R) Wi-Fi 6 AX201 160MHz
    GUID                   : 69deaa61-268f-42f0-abab-d115024094da
    Physical address       : 34:2e:b7:6d:e7:32
    Interface type         : Primary
    State                  : connected
    SSID                   : HomeOffice
    BSSID                  : 78:45:58:fd:b3:76
    Network type           : Infrastructure
    Radio type             : 802.11ac
    Authentication         : WPA2-Personal
    Cipher                 : CCMP
    Connection mode        : Auto Connect
    Band                   : 5 GHz
    Channel                : 36
    Receive rate (Mbps)    : 866.7
    Transmit rate (Mbps)   : 866.7
    Signal                 : 96%
    Profile                : HomeOffice

    Hosted network status  : Not available

This is exactly what I need. I can see the SSID of the network I am connected to. I can use this information to determine if I am at the lake or at home.

Now, I could simply parse this output. It isn't difficult to get the SSID using Select-String.

PS C:\> netsh wlan show interfaces | Select-String "\bSSID\b"

    SSID                   : HomeOffice

The \b indicates a regular expression word boundary. This way I don't match BSSID. I could even go so far as to split the string and get the value.

PS C:\> (netsh wlan show interfaces | Select-String "\bSSID\b").Line.Split(":")[1].Trim()
HomeOffice

However that leaves a lot of potentially useful information on the table. I can envision a situation at a hotel where I want to see my connection speed and signal strength. You don't have to go crazy, but try to avoid MVP coding, that is, the minimum viable product. You can't predict every way a user might want to use your command our its output, so try to make it as rich and useful as possible.

Mapping the Data

Unfortunately, unlike other command-line tools, netsh lacks any sort of formatting option. My work would be so much easier if I could get JSON, or even XML, output. But I can't. So I need to parse the text output and create objects.

The output from netsh already looks like a list of key-value pairs or object properties. I want to work with the lines with a colon (:) in them. I can use Select-String to filter the lines I want.

PS C:\> netsh wlan show interfaces | where {$_ -match " : "}
    Name                   : Wi-Fi
    Description            : Intel(R) Wi-Fi 6 AX201 160MHz
    GUID                   : 69deaa61-268f-42f0-abab-d115024094da
    Physical address       : 34:2e:b7:6d:e7:32
    Interface type         : Primary
    State                  : connected
    SSID                   : HomeOffice
    BSSID                  : 78:45:58:fd:b3:76
    Network type           : Infrastructure
    Radio type             : 802.11ac
    Authentication         : WPA2-Personal
    Cipher                 : CCMP
    Connection mode        : Auto Connect
    Band                   : 5 GHz
    Channel                : 36
    Receive rate (Mbps)    : 866.7
    Transmit rate (Mbps)   : 866.7
    Signal                 : 96%
    Profile                : HomeOffice
    Hosted network status  : Not available

Notice the spaces in the Where-Object filter. This is because I don't want to include the line There is 1 interface on the system:.

What I want to do is create a mapping table that will convert the key-value pairs into properties of an object. I can use a hashtable for this.

netsh wlan show interfaces | where {$_ -match " : "} |
ForEach-Object -Begin { $h = [ordered]@{} } -Process {
    $line = $_.Trim()
    #split into 2 strings
    $data = $line -split ':', 2
    #need to trim spaces from everything and drop the % from the signal
    $h.add($data[0].Trim(), $data[1].trim().replace('%', ''))
}

This code parses each line of the `netsh` output, splitting it into two strings at the colon. The first string is the key, and the second string is the value. I trim any leading or trailing spaces and remove any percent signs from the signal value. I then add the key-value pair to the hashtable. The `-Begin` block initializes the hashtable. The `-Process` block adds each key-value pair to the hashtable. The result is a hashtable that I can use.

```shell
PS C:\> $h

Name                           Value
----                           -----
Name                           Wi-Fi
Description                    Intel(R) Wi-Fi 6 AX201 160MHz
GUID                           69deaa61-268f-42f0-abab-d115024094da
Physical address               34:2e:b7:6d:e7:32
Interface type                 Primary
State                          connected
SSID                           HomeOffice
BSSID                          78:45:58:fd:b3:76
Network type                   Infrastructure
Radio type                     802.11ac
Authentication                 WPA2-Personal
Cipher                         CCMP
Connection mode                Auto Connect
Band                           5 GHz
Channel                        36
Receive rate (Mbps)            866.7
Transmit rate (Mbps)           866.7
Signal                         97
Profile                        HomeOffice
Hosted network status          Not available

I may not have made it clear, but I'm not writing code that I can run at the prompt. I want to create a function that I, or you, can run. Part of that code will be a hashtable I can use in my script file to define the property names. These are preliminary steps I only need to do once. Eventually, I'll write code that will convert the netsh output into an object.

The mapping hashtable I envision shouldn't have spaces or special characters. So I'll refine the data I have in $h.

$h.keys | Foreach-Object -Begin { $o = "@{`n" } -Process {
    $o += "$($_.Replace('\s','')) = '$($_.trim())'`n"
} -End { $o += '}' }

I suppose I could have simply modified $h, but I decided to create another hashtable. This way, if I made a mistake I wouldn't have to recreate $h. Here's where I am so far with $o.

Want to read the full issue?
GitHub Bluesky LinkedIn About Jeff
Powered by Buttondown, the easiest way to start and grow your newsletter.