Assigning New-Objects with ForEach Loop Problem

I’m just a PowerShell noobie trying to create a Powershell script that can be run on a PC to gather information on the WiFi connection. Eventually, it will log the data to a file on the network as a CSV.

I’m not even sure I am explaining the issue correctly. Hopefully, the code bits below will help make it clear. The code is hacked together from a number of sources and does work in its current form. However, I am stuck on optimizing it when assigning New-Objects from an expanded array. Specific values need to be recorded from a netsh command.
Here is the command with output:

PS C:\> netsh wlan show interfaces

There is 1 interface on the system:

Name : Wi-Fi
Description : Realtek RTL8191SU Wireless LAN 802.11n USB 2.0 Network Adapter
GUID : 2844c656-2af3-4818-b819-f6a3b61bce66
Physical address : 00:00:de:ad:be:ef
State : connected
SSID : MyWiFi
BSSID : 11:11:de:ad:be:ef
Network type : Infrastructure
Radio type : 802.11n
Authentication : WPA2-Personal
Cipher : CCMP
Connection mode : Profile
Channel : 6
Receive rate (Mbps) : 300
Transmit rate (Mbps) : 150
Signal : 100% 
Profile : MyWiFi

Hosted network status : Not available

Here is un-optimized code that works:

$attributes = "SSID","BSSID","Channel","Signal" 
$netshResult = Invoke-Command {netsh wlan show interfaces}
$result = @{}

$netshObject = New-Object psobject -Property @{
  SSID = $Null
  BSSID = $Null
  Channel = $Null
  Signal = $Null
}

$netshResult = $netshResult | Select-String : #break into chunks if colon only
$i = 0
while($i -lt $netshResult.Length){
  $line = $netshResult[$i]
  $line = $line -split(":",2)
  $line[0] = $line[0].trim()
  $line[1] = $line[1].trim()
  $result.$($line[0]) = $($line[1])
  $i++
}
$line = $Null
foreach($attribute in $attributes){
  $netshObject.$attribute = $result.$attribute
  If($line -eq $Null){$line = $netshObject.$attribute}Else{$line = $line +","+ $netshObject.$attribute}
}
Write-Host $line

Output

MyWiFi,11:11:de:ad:be:ef,6,100%

To avoid hard-coding the specific values I want (SSID, BSSID, etc) in the $netshObject variable assignment I’ve tried replacing this code block

$netshObject = New-Object psobject -Property @{
  SSID = $Null
  BSSID = $Null
  Channel = $Null
  Signal = $Null
}

with this

$netshObject = New-Object psobject -Property @{
  foreach($attribute in $attributes){
    $attribute = $Null
  }
}

It doesn’t work and throws these errors

At C:\Users\TekMason\WiFiTest-Post.ps1:14 char:12
+ foreach($attribute in $attributes){
+ ~
Missing '=' operator after key in hash literal.
At C:\Users\TekMason\WiFiTest-Post.ps1:23 char:6
+ while($i -lt $netshResult.Length){
+ ~
Missing '=' operator after key in hash literal.
At C:\Users\TekMason\WiFiTest-Post.ps1:23 char:6
+ while($i -lt $netshResult.Length){
+ ~
The hash literal was incomplete.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingEqualsInHashLiteral

I am totally lost on how to make this work and would appreciate any assistance.

Thx,
TekMason

 

 

 

Try this:

$attributes = "SSID","BSSID","Channel","Signal" 
$netshResult = Invoke-Command {netsh wlan show interfaces}
$result = @{}
 
$netshObject = [PSCustomObject]@{}
foreach ($attribute in $attributes) {
Add-Member -InputObject $netshObject -Value $Null -Name $attribute -MemberType NoteProperty
}

$netshResult = $netshResult | Select-String : #break into chunks if colon only
$i = 0
while($i -lt $netshResult.Length){
  $line = $netshResult[$i]
  $line = $line -split(":",2)
  $line[0] = $line[0].trim()
  $line[1] = $line[1].trim()
  $result.$($line[0]) = $($line[1])
  $i++
}

$line = $Null
foreach($attribute in $attributes){
  $netshObject.$attribute = $result.$attribute
  If($line -eq $Null){$line = $netshObject.$attribute}Else{$line = $line +","+ $netshObject.$attribute}
}
Write-Host $line

I forgot to add a brief explanation. The following code:

$netshObject = [PSCustomObject]@{}
foreach ($attribute in $attributes) {
Add-Member -InputObject $netshObject -Value $Null -Name $attribute -MemberType NoteProperty
}

will use the ‘pscustomobject’ type accelerator to create an empty object first and then in the foreach loop use the ‘Add-Member’ cmdlet to add each item in the ‘attributes’ collection as a property of the object that was just created.

Thank you so much, Fer.
I’ve been struggling with it for a while. You made my day!

I was just about to ask if you could provide a dumbed-down explanation of what I was doing wrong.

Cheers,
TekMason

No problem. Glad I could help. This is a different approach but should work just as well.

A foreach loop cannot be inside a hash table, that is where those errors were coming from, you would need key value pairs only, that is what each iteration with Add-Member’ does, it adds a property, which is equivalent to adding a key value pair to that hash table.

I know this is off topic, but if you want more wifi info then you can possibly digest, try this:

“netsh wlan show wlanreport”

From an admin shell.

Hi TonyD,

WoW!

Thanks for posting that. It produces a ridiculous amount of information. I may include that in my script to save the HTML in the same folder as the raw data reads.

Here is the code I have so far:


TM