3

This original question was not about powershell. I am assuming these base premises:

  • We are running Windows 7
  • We want to parse the result of systeminfo utility that comes with Windows 7
  • We want to extract information about network adapters from the output and put it into some data structure for further processing.

Now, I know that there are better ways of getting Network card information than running systeminfo and parsing the output. My interest is not in this particular utility. I'm considering a generic task of parsing / format some text in powershell. I feel that powershell is well suited for this kind of tasks, maybe better than C# (depending on particular requirements). This is why I offer my answer in powershell to the original question.

My question, though is this. I always feel that some of powershell syntax is a bit cumbersome. How would you improve my code? Note that the code does not have to return exactly the same results in exactly the same structure. I'm looking for tricks that can help with text parsing / processing. I've seen once and again community's ingenuity in approaching a lot of task. I've seen simple solutions to complex problems that are not at all obvious until someone shows you how. This is why I'm asking.

Here is the code:

$networkCards = systeminfo | ForEach-Object {$a=0} {
    if ($_.startswith("Network Card(s)")) {$a=1} else {if ($a) {$_}}
}

$networkCards | ForEach-Object {$data=@{}} { 
    if ($_.trim().startswith("[")) {
        $c = $_.trim(); $data[$c] = @()} else {$data[$c] += $_.trim()
    } 
}

#Now we have a hash table with the keys as requested in the question 
#and the values are lists of separate strings, but those can be easily 
#concatenated if needed. Let's display it:
$data

3 Answers 3

1

First of all, please stop using Powershell as usual script language.

PowerShell use object and parsing string is definitively NOT the good way to do what you want. I have to adapt your script to my language to get something in $data

And for me the things here under do not have mush sense but you construct a hashtable of array and I give you the way to exploit it.

So to use the $data you can write :

foreach ($key in $data.keys)
{
  write-Host ("The name is {0}, the value is {1}" -f $key, $data[$key])
}

In my case it gives :

The name is [02]: fe80::391a:2817:8f3e:6f2f, the value is System.Object[]
The name is [02]: Intel(R) WiFi Link 5300 AGN, the value is System.Object[]
The name is [02]: fe80::c70:cc38:cf64:eb27, the value is System.Object[]
The name is [01]: 192.168.183.1, the value is System.Object[]
The name is [01]: 192.168.0.3, the value is System.Object[]
The name is [03]: VMware Virtual Ethernet Adapter for VMnet1, the value is System.Object[]
The name is [05]: Microsoft Virtual WiFi Miniport Adapter, the value is System.Object[]
The name is [02]: fe80::5d48:c4a:5987:ee73, the value is System.Object[]
The name is [04]: VMware Virtual Ethernet Adapter for VMnet8, the value is System.Object[]
The name is [01]: 192.168.234.1, the value is System.Object[]
The name is [01]: Intel(R) 82567LM Gigabit Network Connection, the value is System.Object[]

Because $data[$key] is an array. you can write :

foreach ($key in $data.keys)
{
  write-Host ("The name is {0}" -f $key)
  foreach($line in $data[$key])
  {
    Write-Host ("`t$line")
  }
}

For me it gives :

The name is [02]: fe80::391a:2817:8f3e:6f2f
The name is [02]: Intel(R) WiFi Link 5300 AGN
    Nom de la connexion : Connexion réseau sans fil
    État :                Support déconnecté
The name is [02]: fe80::c70:cc38:cf64:eb27
The name is [01]: 192.168.183.1
The name is [01]: 192.168.0.3
The name is [03]: VMware Virtual Ethernet Adapter for VMnet1
    Nom de la connexion : VMware Network Adapter VMnet1
    DHCP activé :         Non
    Adresse(s) IP
The name is [05]: Microsoft Virtual WiFi Miniport Adapter
    Nom de la connexion : Connexion réseau sans fil 2
    État :                Support déconnecté
The name is [02]: fe80::5d48:c4a:5987:ee73
The name is [04]: VMware Virtual Ethernet Adapter for VMnet8
    Nom de la connexion : VMware Network Adapter VMnet8
    DHCP activé :         Non
    Adresse(s) IP
The name is [01]: 192.168.234.1
The name is [01]: Intel(R) 82567LM Gigabit Network Connection
    Nom de la connexion : Connexion au réseau local
    DHCP activé :         Oui
    Serveur DHCP :        192.168.0.254
    Adresse(s) IP
Sign up to request clarification or add additional context in comments.

4 Comments

thank you for contributing. Could you please elaborate on "First of all, please stop using Powershell as usual script language". I totally and utterly don't understand what you mean.
When you need an information. In Powershel, the game is to find the object (from CmdLets or much of the time .NET classes) which would provide it to you accross his properties or method. WMI is also a good provider.
I'm very familiar with what type of language powershell is, but thank you anyway =)
I'm going to borrow from JPBlanc's answer, and say that when parsing text in Powershell, the game will be to CREATE objects. While this may appear more complicated than simply re-formatting the input text, it simplifies everything else downstream.
0

I'll have a try at moderating the answer above :-) :

Although Powershell can be used to parse information from e.g. systeminfo, there are much better interfaces for information. Have a look at Get-WmiObject. In this case, Get-WmiObject Win32_NetworkAdapter or Win32_NetworkAdapterConfiguration seems to come in mind. There are also Win32_NetworkProtocol and Win32_NetworkConnection that may give you the information you need.

Combine with Select-Object, Sort-Object and Format-Table to present the data you need.

2 Comments

Thank you =) I know about WMI. I even explicitly put that I know that there are better ways of getting the information in my question, because I knew that people would suggest WMI =). This is not what I'm interested it right now. I'm just using this output of systeminfo as an example of text that may require parsing.
Since none of the answers I answers my question, (and this is because of nature of the question, really) I would like to "close" this question, I'm picking one, that I feel is most useful among the three.
0

Everyone talking about objects is correct. The idea is to emit an object from one method directly into another, then act on that object. I'm no guru on PS, but I'm beginning to get the idea. Hopefully, this script will move you forward a little bit.

$text = @"
key1:value1
key2:value2
key3:value3
"@
$map = @{}
($text -split "`n") | Where-Object {$_ -imatch 'key2'} | foreach-object {$tokens = $_ -split ":"; $map.Add($tokens[0],$tokens[1])}
$map

1 Comment

It's quite similar to what I'm doing in my example, I think? Or is there a concept you are using, that I overlooked?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.