【问题标题】:Powershell Re-Use a hash Table foreach loopPowershell 重新使用哈希表 foreach 循环
【发布时间】:2014-11-28 13:18:55
【问题描述】:

我对 PowerShell 很陌生,我怀疑我不是程序员,所以我的问题的原因可能对你们大多数人来说很明显。基本上我的脚本错误与

“无法索引到空数组。”

在静态配置的多宿主服务器中循环收集每个网络适配器的属性。我的调试语句显示 foreach 和 if 按预期工作 - 但似乎我无法在 foreach 循环中重用哈希表。这里的正确方法是什么? (注意:这是一个 400 行脚本的一部分,主要集中在哈希表周围,所以我需要尽可能使用哈希表)。

    # hugely truncated.

    $this = @() # initialise results table as an array.
    $ip = "myserver.mydomain.com"


    foreach ($connected_nic in ($Adapter = Get-WmiObject -computer $ip win32_networkadapter -filter "NetConnectionStatus='2'" | where {$_.PNPDeviceID -notmatch "1394"})) { # Find electrically connected adapters, which are not firewire.

    Write-host -ForegroundColor Green $Connected_nic

    if ($cfg=($dns=(Get-WmiObject -ComputerName $ip Win32_NetworkAdapterConfiguration -filter "Index = '$($connected_nic.Index)'")).IPaddress -like "192.168.*") { # test each connected adapter to see if it's IP = 192.168.X.X

    $ips = $dns | select -expandproperty Ipaddress
    $dns # check return is as expected.

    $results = [ordered] @{

    'Netbios Name' = $dns.DNSHostname
    'IPv4 Address' = $ips[0] #cope with ipv6
    'Subnet Mask' = [String]$dns.IpSubnet
    'Default Gateway' = [String]$dns.DefaultIPGateway
    'Primary DNS Server' = $dns.DNSServerSearchOrder[0]
    'Secondary DNS Server' = $dns.DNSServerSearchOrder[1]
    'MAC Address' = $dns.MACaddress
    }

    $dnsout = New-Object PSObject -Property $results # Create a new row for the report from our hash table.
    $this += $dnsout # Add this row to the main report.

    } # Configurations of interest test.
    } # End connected adapter test


    #output



    Netbios Name         : server
    IPv4 Address         : 192.168.228.54
    Subnet Mask          : 255.255.255.0
    Default Gateway      : 192.168.228.5
    Primary DNS Server   : 192.168.228.51
    Secondary DNS Server : 192.168.224.51
    MAC Address          : 00:23:7D:22:1C:52

    Netbios Name         : server
    IPv4 Address         : 192.168.228.54
    Subnet Mask          : 255.255.255.0
    Default Gateway      : 192.168.228.5
    Primary DNS Server   : 192.168.228.51
    Secondary DNS Server : 192.168.224.51
    MAC Address          : 00:23:7D:22:1C:52

    Netbios Name         : server
    IPv4 Address         : 192.168.228.54
    Subnet Mask          : 255.255.255.0
    Default Gateway      : 192.168.228.5
    Primary DNS Server   : 192.168.228.51
    Secondary DNS Server : 192.168.224.51
    MAC Address          : 00:23:7D:22:1C:52


    Connected adapter configurations

    DHCPEnabled      : False
    IPAddress        : {192.168.228.54}
    DefaultIPGateway : {192.168.228.5}
    DNSDomain        : 
    ServiceName      : l2nd
    Description      : HP NC373i Multifunction Gigabit Server Adapter #2
    Index            : 2

    DHCPEnabled      : False
    IPAddress        : {192.168.1.1}
    DefaultIPGateway : 
    DNSDomain        : 
    ServiceName      : VMnetAdapter
    Description      : VMware Virtual Ethernet Adapter for VMnet1
    Index            : 9

    DHCPEnabled      : False
    IPAddress        : {192.168.18.1}
    DefaultIPGateway : 
    DNSDomain        : 
    ServiceName      : VMnetAdapter
    Description      : VMware Virtual Ethernet Adapter for VMnet8
    Index            : 10

编辑以增加细节。 在示例中,计算机具有三个有效的网络适配器,它们将返回三组配置结果。每组结果对于该网络适配器都是唯一的。当我在我的代码中启用调试日志记录时,我可以看到 foreach 和 if 语句正在按照我的意愿执行它们的逻辑并返回三组独特的结果。我的问题是捕获输出没有按预期工作。正在发生的事情是,我最终得到了三组完全相同的结果。现在,您可能很想说明某事因此是空的并且不能覆盖第一组结果 - 然而 - 这不是真的。我肯定会得到三组不同的结果,但是当我尝试哈希表时,只有第一组结果被成功列出。下次我尝试添加更多结果 AKA 覆盖时 - 它失败,无法索引到空数组。只需复制我的代码并在任何具有多个处于活动状态的适配器的计算机上运行它,它就会出错。我想知道如何使它不是 barf 并成功覆盖哈希表中的第一组结果。就是这个问题。

是的,您完全正确 - 感谢您对我的耐心等待。 我现在确切地看到了问题所在——我的测试对象恰好是一个糟糕的选择。 代码实际上很好。非常感谢!

-ea静默继续#完美运行。

【问题讨论】:

  • “在 foreach 循环中重用哈希表”是什么意思?每次循环循环时,您都会覆盖变量 $results,这是您建立哈希表的唯一位置。
  • 我强烈建议您不要尝试内联所有内容,因为它使调试几乎不可能。如果在 foreach 循环中您想要访问除当前 $connected_nic 之外的哈希表的任何成员,那么您需要将哈希表存储在一个变量中,您可以在循环中引用该变量。 FWIW 将结果缓存在 this() 数组变量中是一种 powershell 反模式。你应该把你的新对象放在管道上,让 format-table 或 format-list 甚至 export-csv 来处理剩下的事情。
  • 感谢您查看此内容 - 您能否详细说明我将如何将结果放入管道并让 format-xxxx 照您说的那样处理?
  • 您对我的帖子的编辑建议应该是评论。我已经解释了为什么这不起作用,Matt 详细说明了这一点。这是因为 $dns.dnsserversearchorder 是空的,没有要索引的数组。在 ise 中运行您的脚本,然后只需在控制台部分键入 $dns.dnsserversearchorder[0],您将返回导致脚本失败的错误,并确认我们是正确的。问题是您返回的 nics 具有此属性为空,您需要在尝试构建哈希表之前将其过滤掉。
  • 是的,您完全正确 - 感谢您对我的耐心等待。我现在确切地看到了问题所在——我的测试对象碰巧是一个糟糕的选择。代码实际上很好。非常感谢! -ea静默继续#完美运行。

标签: powershell foreach hashtable overwrite


【解决方案1】:

您的信息相当模糊。我不确定您是在问为什么会收到特定的错误消息,还是在问如何做其他事情。无论如何,假设您只是询问为什么会收到错误消息 - 错误可能发生在以下 3 个位置之一:

'IPv4 Address' = $ips[0] #cope with ipv6
'Primary DNS Server' = $dns.DNSServerSearchOrder[0]
'Secondary DNS Server' = $dns.DNSServerSearchOrder[1]

$ips 或 $dns 变量为空,或者您使用的属性为空。当您尝试像正在做的那样获取索引,但数组不存在时,它将返回您看到的错误。

你可以通过尝试获取一个不存在的数组的索引来看到这一点:

$dontexist[5]

【讨论】:

  • 虽然DNSServerSearchOrder$dns 对象的有效属性,但它在我的大多数网卡上都是空的。这就是错误来自使用上述代码的地方。
猜你喜欢
  • 2021-07-08
  • 2021-06-22
  • 2018-12-11
  • 1970-01-01
  • 2021-11-25
  • 2018-06-27
  • 2016-06-13
  • 1970-01-01
  • 2013-01-30
相关资源
最近更新 更多