0
votes

A PowerShell script is failing on certain servers. PowerShell version on the server where it fails is 2.

Here is the code:

(Get-WmiObject Win32_NetworkAdapterConfiguration -Filter "ipenabled = 'True'").IPAddress[0]

On the server where it works, the output is the IP address of the server. As an example:

10.1.1.1

On the server where it fails, here is the output:

Cannot index into a null array. At line:1 char:90
+ (Get-WmiObject Win32_NetworkAdapterConfiguration -Filter "ipenabled = 'True'").IPAddress[ <<<< 0]
    + CategoryInfo : InvalidOperation: (0:Int32) [], RuntimeException

A major difference between the servers are:

  1. Where it works (as per my observations); there is a single IP address (Single NIC).
  2. On the server where it fails, there are multple NICs with different subnets (so one IP will be 10.x.x.x and second will be 172.x.x.x) -- I would want the script to pick up IP starting 10.x.x.x.

Here is the output if I remove .IPAddress[0]:

Script:

(Get-WmiObject Win32_NetworkAdapterConfiguration -Filter "ipenabled = 'True'")

Output on working server:

DHCPEnabled      : False
IPAddress        : {10.x.x.x}
DefaultIPGateway : {10.x.x.x}
DNSDomain        :
ServiceName      : NIC
Description      : NIC NAME
Index            : 11

Output on servers where the script fails:

DHCPEnabled      : False
IPAddress        : {172.x.x.x}
DefaultIPGateway :
DNSDomain        :
ServiceName      : l2nd
Description      : NIC #34
Index            : 13

DHCPEnabled      : False
IPAddress        : {10.x.x.x}
DefaultIPGateway : {10.x.x.x}
DNSDomain        :
ServiceName      : iANSMiniport
Description      : 
Index            : 20
1
Arrays do not have IPAddress property, and member enumeration was "invented" in PowerShell v3, so it will not work in v2. - user4003407
How would I make the script backward compatible to version 2? - Parth Maniar
Get-WmiObject ... | Select-Object -First 1 -Expand IPAddress - Ansgar Wiechers
While this does give an output. It will not work unless as we're looking for IP addresses starting from "10". Could you help with that? - Parth Maniar
Please consult a PowerShell tutorial. Filtering items by property values is about as basic as it gets. - Ansgar Wiechers

1 Answers

0
votes

Here are the two answers I found on Reddit which I'm exploring. Both of them are working:

1:

Doing (something).member[index] makes a LOT of assumptions. I often prototype code like this, but then I change it for better validation. So, let's break it down...

(something).member[index]

First, (something) has to evaluate in to a valid object, or the rest of the statement won't go as expected. What happens if an error is thrown?

Then, .member is making an assumption that the object contains this property, which is not guaranteed, because (something) isn't handled in a foolproof manner above.

Finally, [index] is making an assumption that you have an array/container/list/whatever of more than one object. I run in to this issue a lot, and depending on circumstances the behavior is not always consistent, so I make sure to confirm (where it's really important) whether I have a single object or more, or just use a different approach.

A lot of the issues can be avoided by piping and using cmdlets instead of directly accessing members and making assumptions. Like /u/SeeminglyScience said, this would work better...

something | select-object member

This way if something returns nothing, the pipe won't go any further.

If member may be a container, and you want all elements...

something | select-object -expandproperty member

And, if member may be a container, and you want only the first element...

something | select-object -expandproperty member | select-object -first 1

So, in your case...

Get-wmiobject win32_networkadapterconfiguration | Select-Object -ExpandProperty IPAddress | Select-Object -First 1

And if you want to filter IP's for all 10.x, I got this to work for me...

Get-wmiobject win32_networkadapterconfiguration | Select-Object -ExpandProperty IPAddress | Where-Object {$PSItem -match "10\.\d{1,3}\.\d{1,3}\.\d{1,3}"}

At this point you should either get a value with the IP or $null, and that is much simpler to handle down the line.

  1. Second solution:

    $1stOctet = '192' $IPInfo = Get-WmiObject win32_networkadapterconfiguration -filter "ipenabled = 'True'" | Where-Object {$_.IPAddress -match "^$1stOctet"} | Select-Object -ExpandProperty IPAddress