【问题标题】:Powershell loop exits earlyPowershell 循环提前退出
【发布时间】:2017-11-21 20:01:10
【问题描述】:

这非常愚蠢,但我的循环显然在进入第二个循环之前就退出了。

脚本的作用是计算服务器上以太网卡的硬件总线和功能编号(通常包含至少 2 个或更多端口)。总线通常对应服务器中的一个芯片/卡,功能号通常对应具体的端口。

示例场景 - 具有 2 个双端口以太网卡的服务器在运行 get-netadapterhardwareinfo 时可能如下所示:

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

您可以看到脚本在“总线 1”上运行,但循环在“总线 2”被处理之前退出。

这条线应该可以处理它

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

并且“小于或等于”对于第二个循环应该评估为真。我在最后放了一些写主机来调试循环,它似乎退出了。

完整的脚本:

#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

    }

【问题讨论】:

  • BusNumber 存在于哪里?我在您的示例中看到有一个Bus 属性,但没有BusNumber。此外,您的 $allnicinfo 变量应该具有 .Count 属性,因为它是一个数组。
  • $它是 get-netadapterhardwareinfo cmdlet 的属性。似乎没有计数,为什么我不确定。你可能是对的,我应该将它存储为一个数组,但我认为它不会解决我的循环问题。
  • 你为什么使用For而不是ForEach循环?似乎有点令人费解。您所做的只是重命名适配器
  • 没有什么好理由,似乎我想做的事情(循环通过每条总线并根据函数编号重命名适配器)它会起作用。

标签: windows powershell system


【解决方案1】:

按照您的逻辑,这是您的脚本的清理版本,它应该会更好地工作。首先,我们创建一个 $Nics 数组来执行计算,这样您就不需要不断地轮询您的硬件(慢)。屏蔽变量名也是一种不好的做法(在两个循环中都使用 $i)。

## 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
    }
}

这是可以安全运行的,请注意-WhatIf

【讨论】:

  • 完美运行,谢谢!我会尽量避免使用其他方法!
【解决方案2】:

我对你的代码有点困惑,认为你可以简单一点。见下文

$NetAdapterHardwareInfo = Get-NetAdapterHardwareInfo
foreach ( $NetAdapter in $NetAdapterHardwareInfo )
{
    $NewName = 'B{0} Port{1}' -f $NetAdapter.Bus,($NetAdapter.Function + 1) 
    Rename-NetAdapter $NetAdapter.Name -NewName $NewName -WhatIf
}

如果你离开-WhatIf,你会得到这样的输出:

如果:重命名-NetAdapter -Name 'Wi-Fi' -NewName 'B58 Port1'

如果:重命名-NetAdapter -Name 'Ethernet' -NewName 'B0 Port7'

当您想将其投入生产时,您可以删除 -WhatIf

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    相关资源
    最近更新 更多