Search code examples
powershellcommand

Why is Get-NetIPAddress not working on certain servers?


This is my code:

Function Read-NetworkInfo # retrieves list of NICs that are running
{
Get-NetAdapter | Where-Object -Property Status -eq -Value 'Up'
}

Function Get-NetworkInfo 
{ 
Write-Host "Network Information:" -ForegroundColor Green; $lineBreak
$nicList = Read-NetworkInfo 
foreach($nic in $nicList) 
{
$macAddress = ($nic).MacAddress
$prefixLength = (Get-NetIPAddress -InterfaceAlias $nic.Name -AddressFamily IPv4).PrefixLength 
$ipAddress = (Get-NetIPAddress -InterfaceIndex $nic.ifIndex).IPv4Address 
$ipAddress = [string]$ipAddress
$prefixLength = [int]$prefixLength


$firstOctet = 255 
$secondOctet = [int](([version] $ipAddress).Minor)
$thirdOctet = [int](([version] $ipAddress).Build)
$fourthOctet = [int](([version] $ipAddress).Revision)


if($prefixLength -le 16)
{
  $difference = $prefixLength - 8
  $secondOctet = 256 - ([Math]:: Pow(2, $prefixLength  - (2 * $difference)))
  $thirdOctet = 0 
  $fourthOctet = 0
}
elseif ($prefixLength -le 24)
{
  $difference = $prefixLength - 12
  $secondOctet = 255
  $thirdOctet = 256 - ([Math]:: Pow(2, $prefixLength - (2 * $difference)))
  $fourthOctet = 0

}
else 
{
  $difference = $prefixLength - 16
  secondOctet = 255
  $thirdOctet = 255
  $fourthOctet = 256 - ([Math]:: Pow(2, $prefixLength - (2 * $difference)))
  
}

  
[string]$netmask = '0.0.0.0' 
$octets = $firstOctet, $secondOctet, $thirdOctet, $fourthOctet
$netmask = $octets -join('.')

# print outs
Get-NetIpConfiguration -InterfaceAlias $nic.Name
Write-Host "Mac Address: " -ForegroundColor Green -NoNewline; Write-Host $macAddress 
Write-Host "Net Mask: " -ForegroundColor Green -NoNewline; Write-Host $netmask
# formatting / organizing the NIC information when the array of NICs is greater than 1
if ($nicList.length -gt 1)
{
    Write-Host $separator 
}
$lineBreak

}
}

It works when I run it in certain servers, otherwise it gives me the message:

Get-NetIPAddress : No matching MSFT_NetIPAddress objects found by CIM query for instances of the
ROOT/StandardCimv2/MSFT_NetIPAddress class on the CIM server: SELECT * FROM MSFT_NetIPAddress  WHERE ((InterfaceAlias
LIKE 'NIC2')) AND ((AddressFamily = 2)). Verify query parameters and retry.
At line:50 char:22
+ ... ixLength = (Get-NetIPAddress -InterfaceAlias $nic.Name -AddressFamily ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo         : ObjectNotFound: (MSFT_NetIPAddress:String) [Get-NetIPAddress], CimJobException
    + FullyQualifiedErrorId : CmdletizationQuery_NotFound,Get-NetIPAddress

The codes function is to retrieve Network interface cards but for some reason the command "Get-NetIPAddress" is causing problems on certain servers.

I haven't tried anything yet to fix it as im not sure where the problem is stemming from.


Solution

  • Ok, I see the issue here, you're assuming that every NetAdapter has an IP. There's going to be some virtual NetAdapters on some machine depending on what their software load is, often times sharing MAC addresses with other NetAdapters. In such cases your virtual adapters will commonly not have an IP, and will just be used to translate traffic on the same MAC address used by another adapter in the system.

    On the machines that throw that error I'm guessing you can do:

    Get-NetAdapter|Where Status -eq 'Up'|Select Name,HardwareInterface,MacAddress
    

    And you'll see the virtual adapters that don't have an IP tied to them all reporting False for HardwareInterface, and matching another adapter with the same MAC address.

    To avoid this you can get IP addresses, and then match those to your adapters. Something like:

    Function Get-NetworkInfo 
    { 
    Write-Host "Network Information:" -ForegroundColor Green; $lineBreak
        $nicList = Read-NetworkInfo
        $ipList = Get-NetIpAddress
        ForEach($nic in $nicList){
            if($nic.interfaceIndex -notin $ipList.InterfaceIndex){continue}
            <the rest of your code for that function>
    

    Also, a shorter way to get CIDR to Subnet that I keep on hand, in case you want to use it:

    Function CIDRTo-Subnet ([int32]$CIDR){
        4..1|% -Begin {
            $CIDRBinary = [convert]::ToInt64(('1'*$CIDR).PadRight(32,'0'),2);
            $SNArr = @()
        } -Process {
            $SNArr += [math]::Truncate($cidrbinary%[math]::Pow(256,$_)/([math]::Pow(256,$_)/256))
        } -End {$SNArr -join '.'}
    }
    

    Then you can reduce most of that to just:

    $subnet = CIDRTo-Subnet $prefixLength