Вывод массива массивов в Powershell / Powercli усекается с эллипсами

Цель моего сценария - получить весь список виртуальных машин от нашего vcenter, проверить, есть ли у них записи DNS - если запись dns равна нулю, то вывести имя виртуальной машины и соответствующий IP-адрес. Довольно просто, но меня смущает объединение массива имен виртуальных машин с массивом IP-адресов. Вот что я имею в виду:

$mainArray = @()
$vmArray = @()
$ipArray = @()

$vms = Get-VM | select Name, @{N="DnsName"; E={$_.ExtensionData.Guest.Hostname}}, @{N="IPAddress"; E={$_.Guest.IPAddress[0]}}

foreach ($vm in $vms)
{
   $dnsname = $vm.DnsName
   $ipaddr = $vm.IPAddress
   $vmname = $vm.Name

    if (!$vm.DNSName) #if DNS name is null
    {
       $vmArray += $vmname
       $ipArray += $ipaddr
     }
}       

$item = New-Object PSObject
$item | Add-Member -type NoteProperty -Name 'VM Name' -Value $vmArray
$item | Add-Member -type NoteProperty -Name 'IP Address' -Value $ipArray

$mainArray += $item

$mainArray | ft -wrap -autosize

Это выводит два столбца рядом друг с другом, но вывод разделяется запятыми и усекается эллипсом. Я знаю, что есть лучший способ сделать это, поэтому я открыт для предложений. Также было бы интересно узнать, как сделать эту работу только для моего собственного понимания. Ценю помощь всех.

2 ответа

Ваша основная проблема заключается в том, что вы заполняете массив вне цикла. У меня сейчас нет доступа к PowerCLI, но мы должны быть в состоянии удалить большую часть этого кода, так как он кажется избыточным и ненужным. Продолжая после $vms быть объявленным

$vms | Where-Object{!$_.DNSName} | ForEach-Object{

    New-Object PSObject -Property @{
        'VM Name' = $_.Name
        'IP Address' = $_.IPAddress
    }
} | ft -wrap -autosize

Прежде чем вы сделали два массива. Один для имен, а другой для ips. Затем вы взяли эти 2 массива и сделали один объект с этими двумя свойствами. Я убрал необходимость в операторе if с Where-Object{!$_.DNSName}, Теперь все обрабатываемые объекты - это те, которые вам нужны.

Вы действительно можете сделать это в одну / две строки, используя ту же логику.

Get-VM | Select @{N='VM Name';E={$_.Name}}, @{N="DnsName"; E={$_.ExtensionData.Guest.Hostname}}, @{N="IP Address"; E={$_.Guest.IPAddress[0]}} |
    Where-Object{!$_.DNSName} | Select "VM Name","IP Address" | Format-Table -wrap -autosize

Опять же, я не могу проверить, но это должно работать. Если есть какие-либо ошибки, они должны быть легко исправимы. Предполагая, что я разобрался с вашей проблемой в первую очередь.

Об эллипсах

PowerShell имеет переменную $FormatEnumerationLimit это определяет, сколько элементов массива отображается в выводе консоли. Есть хорошая статья, которая обсуждает это на TechNet

По умолчанию $FormatEnumerationLimit установлено на 4

Мэтт, я нашел эту ссылку ранее, но не нашел ее очень полезной, поскольку она искажает вывод и не разбивает значения по строкам. Вот как я смог заставить оригинальный скрипт работать:

$i=0

write-output $vmArray |
foreach {
new-object psobject -property @{
                                VMName = $_
                                IPAddress = $ipArray[$i++]
                             }
    }   | ft -auto -wrap

Скорее нетрадиционно, но, тем не менее, работает. Там действительно должен быть более простой способ объединить массив бок о бок, но я отвлекся. Большое спасибо, Мэтт.

Обновление: это, вероятно, более условно:

    For($i=0;$i -lt $vmArray.Count;$i++)
    {
    $item = New-Object PSObject
    $item | Add-Member -type NoteProperty -Name 'VM Name' -Value    $vmArray[$i]
    $item | Add-Member -type NoteProperty -Name 'IP Address' -Value $ipArray[$i]
    $mainArray += $item
      }

$mainArray | ft -wrap -autosize 
Другие вопросы по тегам