Search code examples
windowspowershellsystem

Powershell loop exits early


This is extremely stupid, but my loop is exiting before it gets to the second loop apparently.

What the script does is counts the hardware bus and function number from ethernet cards on a server (usually contain at least 2 ports or more). The bus usually corresponds to a chip/card in the server, and the function number usually the specific port.

Example scenario - a server with 2 dual-port ethernet cards might look like this when you run get-netadapterhardwareinfo:

name     Bus Function
----     --- --------
PORT4      2        1
PORT3      2        0
B1 Port2   1        1 
B1 Port1   1        0

You can see the script runs on "bus 1" but then the loop exits before "bus 2" can be processed.

This line is supposed to handle it

for($i = 1; $i -le $buscount.Maximum; $i++)

and the "less than or equal" should evaluate as true for the second loop. I put in some write-hosts at the end to debug the loop, it seems to exit.

FULL SCRIPT:

#BEGIN
#collect hardware information, determine ports.
$allnicinfo = Get-NetAdapterHardwareInfo | Select Name, InstanceID, InterfaceDescription, BusNumber, FunctionNumber

#determine how many adapters exist
$buscount = Get-NetAdapterHardwareInfo | select -ExpandProperty busnumber | measure-object -maximum | select Maximum

#improve the bus count method
for($i = 1; $i -le $buscount.Maximum; $i++)
    {
    $bus = $i

    $funccount= @()
    $funccount = $allnicinfo | where-object {$_.busnumber -eq $i} | select -expandproperty functionnumber | measure-object -Maximum | select Maximum
    for($i = 0; $i -le $funccount.Maximum; $i++)
        {
        $nic = Get-NetAdapterHardwareInfo | where {($_.busnumber -eq $bus) -and ($_.functionnumber -eq $i)}
        $port = $i + 1
        Rename-NetAdapter $nic.Name "B$bus Port$port"
        }
    write-host $bus
    write-host $i

    }

Solution

  • Following your logic, here's a cleaned up version of your script that should work better. First we create an array of $Nics to perform calculations against so you don't need to constantly poll your hardware (slow). It's also a bad practice to mask variable names (using $i in both of your loops).

    ## Collect hardware information, determine ports
    $Nics = @(
        Get-NetAdapterHardwareInfo |
            Select-Object -Property @('Name', 'InstanceID', 'InterfaceDescription', 'BusNumber', 'FunctionNumber')
    )
    
    ## Rename logic
    For ($i = 0; $i -le $Nics.Count; $i++)
    {
        $FunctionCount = (($Nics | Where-Object { $_.BusNumber -eq $i }).FunctionNumber | Measure-Object -Maximum).Maximum
    
        For ($j = 0; $j -le $FunctionCount; $j++)
        {
            $Nic = $Nics | Where-Object { $_.BusNumber -eq $i -and $_.FunctionNumber -eq $j }
            Rename-NetAdapter -Name $Nic.Name -NewName "B$i Port$($j + 1)" -PassThru -WhatIf
        }
    }
    

    This is safe to run, do note -WhatIf