I object to ipconfig

The beauty of Powershell is that everything in Powershell is an object. You take objects, pass them to objects, and get objects back. One of the other great features of Powershell is compatibility with older CMD commands. The problems arises though when we want to get the two working together.

A big issue with regular commands is the each one has its own way of displaying output. Interpreting and using this output programmatically can be tricky at best. Mostly for the sake of an example, I'd like to walk through the process of objectifying the output of ipconfig.

To begin, we will need to run ipconfig and store the output in a variable. However, when we run it, lets filter down as much as possible with some broad parsing and then we can filter it down and fine tune our parsing as we get closer to the actual information we want.

So here we go:

   1: PS C:\> $ip = ipconfig | Select-String "IPv4|Subnet|Gateway" | select-object -first 3
   2: PS C:\> $ip
   3:  
   4:    IPv4 Address. . . . . . . . . . . : 192.168.15.220
   5:    Subnet Mask . . . . . . . . . . . : 255.255.255.0
   6:    Default Gateway . . . . . . . . . : 192.168.15.1
   7:  
   8:  
   9: PS C:\>

Using select-string we can get all the lines that have "IPv4 OR Subnet OR Gateway." Next we pipe this to select-object and select the first 3 lines that match our criteria. This way we are only getting the first adapter.

Now that we have this info store in the variable $ip we can start looking at parsing out the different lines. Lets just look at working with the first line as a demonstration.

   1: PS C:\> $ip[0]
   2:  
   3:    IPv4 Address. . . . . . . . . . . : 192.168.15.220
   4:  
   5: # Use multi variable assignment to get the output of the split on the string
   6: # Note that we split on ":" so we IPv4 Address set to $prop and the IP Address 
   7: # gets set to $value
   8:  
   9: PS C:\> $prop,$value = $ip[0].ToString().Split(":")
  10: PS C:\> $prop
  11:    IPv4 Address. . . . . . . . . . .
  12: PS C:\> $value
  13:  192.168.15.220
  14:  
  15: PS C:\> # Now lets clean it up a bit
  16:  
  17: PS C:\> $prop.Trim(" :")
  18: IPv4 Address. . . . . . . . . . .
  19:  
  20: # Trim off the spaces and periods.
  21: PS C:\> $prop.Trim(". :")
  22: IPv4 Address
  23:  
  24: # for this we can just trim off the leading space
  25:  
  26: PS C:\> $value
  27:  192.168.15.220
  28: PS C:\> $value.Trim()
  29: 192.168.15.220

We use the split method to extract the property and value, essentially cutting each line in half at the ":"

Once we get the individual property and value entries we can clean them up with a little haircut... using the Trim method.

The last thing we will need to do is add these properties and their values to an object. This is accomplished using the add-member cmdlet.

   1: PS C:\> $prop = $prop.Trim(". :")
   2: PS C:\> $prop
   3: IPv4 Address
   4: PS C:\> $value = $value.Trim()
   5: PS C:\> $value
   6: 192.168.15.220
   7: PS C:\> $ipo = New-Object psobject
   8: PS C:\> Add-Member -InputObject $ipo noteproperty -Name $prop -Value $value
   9: PS C:\> $ipo
  10:  
  11: IPv4 Address
  12: ------------
  13: 192.168.15.220
  14:  
  15:  
  16: PS C:\>


Now if we wrap all this up into a foreach-object command.

   1: PS C:\> $ip = ipconfig | Select-String "IPv4|Subnet|Gateway" | select-object -first 3
   2: PS C:\> $ip | % {$ipo = New-Object psobject} {$prop,$value = $_.ToString().Split(":");
   3: >> Add-member -InputObject $ipo noteproperty -Name $prop.Trim(". :") -Value $value.Trim()}
   4: >>
   5: PS C:\> $ipo
   6:  
   7: IPv4 Address                                              Subnet Mask                                               Default Gateway
   8: ------------                                              -----------                                               ---------------
   9: 192.168.15.220                                            255.255.255.0                                             192.168.15.1
  10:  
  11:  
  12: PS C:\> $ipo | fl *
  13:  
  14:  
  15: IPv4 Address    : 192.168.15.220
  16: Subnet Mask     : 255.255.255.0
  17: Default Gateway : 192.168.15.1
  18:  
  19:  
  20:  
  21: PS C:\>

Really the only tricky thing here is that we changed $ip[0] to $_ so we could process the current object each time using the "%" which is the alias for the ForEach-Object cmdlet..

This is all sweet and nice but still its a lot of work for one command and doing all the string manipulation is  a bit tough, and not repeatable for other commands. So this brings up a question for which I do not have an answer. in the long run,  do we adopt commands and coerce them into the world of objects or do we build functions/Cmdlets to replace them.

I am sure the answer is the same as what my grandpa said when I asked him if he wears briefs of boxers... "Welll.. Depends"

What say you ?

Andy

Comments (1) -

gwmi Win32_NetworkAdapterConfiguration

Comments are closed