@volgodin

Почему бесконечный цикл срабатывает несколько раз, прежде чем начаться снова?

Есть код, который спрашивает имя пк и выдаёт сведения о машине. Всё было предсказуемо до тех пор, пока не решил сделать форматированный вывод дисков с выбранными названиями столбцов и проверкой версии windows (предполагается, что xp в парке машин нет и будут проверяться только 10+ версии).
Теперь вывод информации отрабатывает три раза, а имя проверяемого пк спрашивает дважды. Такое поведение вызывает строка с SELECT.
Не понимаю каким образом тогда сделать вывод дисков с кастомными названиями столбцов в цикле if? А в идеале бы понять такое поведение select'а с хэш-таблицами powershell

$ArrComputers = @()

while(1) { 
    $ArrComputers += Read-Host("Введите имя компьютера")

    foreach ($Computer in $ArrComputers) {

        if (Test-Connection $computer -count 1 -quiet) {
            $computerDrives = Get-WmiObject -Class MSFT_PhysicalDisk -Namespace "root\Microsoft\Windows\Storage" -Computer $computer 
            $computerOS = get-wmiobject Win32_OperatingSystem -Computer $Computer

            if ($computerOS.Version -notlike "6.*") {
               $computerDrives | Select @{n = 'Диск'; e = { $_.FriendlyName } }, @{n = 'Объём ГБ'; e = { [math]::Round($_.Size / 1GB) } } 
            }
            "ОС: " + $computerOS.caption + ", Service Pack: " + $computerOS.ServicePackMajorVersion
            "конец`n"
        }
    }
}

Получаемый вывод
Введите имя компьютера: pc-26
Введите имя компьютера: pc-26
Диск        Объём ГБ
----        --------
ADATA SU650   112,00
ОС: Майкрософт Windows 10 Pro, Service Pack: 0
конец

ADATA SU650   112,00
ОС: Майкрософт Windows 10 Pro, Service Pack: 0
конец

ADATA SU650   112,00
ОС: Майкрософт Windows 10 Pro, Service Pack: 0
конец


UPD.
Оказалось вместо select'a лучше использовать сразу таблицу с форматированными столбцами

if ($computerOS.Version -notlike "6.*") {
            ""
            (Get-WmiObject -Class MSFT_PhysicalDisk -Namespace "root\Microsoft\Windows\Storage" -Computer $computer `
            | ft `
            @{n = 'Диск'; e = { $_.FriendlyName } }, `
            @{n = 'Объём ГБ'; e = { [math]::Round($_.Size / 1GB) } } `
            | Out-String).Trim()
        }
  • Вопрос задан
  • 339 просмотров
Решения вопроса 1
@NortheR73
системный инженер
Не понимаю необходимость бесконечного цикла.
Теперь вывод информации отрабатывает три раза, а имя проверяемого пк спрашивает дважды
потому что вы добавляете введенное имя компа в набор $ArrComputers, а потом дергаете каждый раз весь $ArrComputers через ForEach, т.е. первый ответ на первый ввод, второй и третий ответы - на второй ввод, т.к. в наборе уже два имени

По скрипту вижу такие варианты:
1. Если Вы хотите, чтобы скрипт постоянно висел и спрашивал имя компа (цикл While), тогда набор $ArrComputers и цикл ForEach не нужны, т.е. спросили имя - обработали запрос
2. В переменную $ArrComputers имена компов можно передать через запятую, т.е.
$ArrComputers = Read-Host("Введите имена компьютеров через запятую")

Далее передаете $ArrComputers в параметре -ComputerName командлету Get-WmiObject и форматируете вывод как вам надо:
$computerDrives = Get-WmiObject -Class MSFT_PhysicalDisk -Namespace "root\Microsoft\Windows\Storage" -ComputerName $ArrComputers | Format-Table (или Format-List) prop1,prop2...  
$computerOS = get-wmiobject Win32_OperatingSystem -ComputerName $ArrComputers

Цикл ForEach не нужен
3. Убираем цикл While вообще. Набор $ArrComputers заполняем именами компов из какого-нибудь файла, далее обрабатываем их в цикле ForEach.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы