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
.