Назад | Перейти на главную страницу

Пустой вывод сценария Powershell для второй функции

Я пишу большой скрипт, который сканирует информацию WMI с компьютеров в AD. У меня есть функции для diskinfo, raminfo и videocardinfo, где диск и видеокарта имеют похожие стили вывода. Проблема в том, что в зависимости от порядка, в котором скрипт запускает их, любой вывод будет пустым. Вот две функции:

function Get-DiskInfo {

$disk = Get-WMIObject Win32_Logicaldisk -ComputerName $computer |
        Select  @{Name="Computer";Expression={$computer}}, DeviceID,
        @{Name="SizeGB";Expression={$_.Size/1GB -as [int]}},
        @{Name="FreeGB";Expression={[math]::Round($_.Freespace/1GB,2)}}
        Write-Host $Computer
        $disk

}

и:

function Get-VRamInfo {

$vram = Get-WmiObject win32_videocontroller -ComputerName $computer | 
        Select @{Name="Computer";Expression={$computer}},
        @{Name="VideoRAM";Expression={$_.adapterram / 1MB}},
        Name
        Write-Host $computer
        $vram

}

Один получит предполагаемый результат, но тот, который будет запущен позже в скрипте, выведет только имена компьютеров, но не информацию

вот полный сценарий: https://gist.github.com/ErkkaKorpi/f1b10a62ac79763fa38082b6c25e8f1b

В чем может быть проблема?

По непонятным причинам Write-Output командлет запоминает свойства настраиваемого объекта от его первого / предыдущего использования для любого следующего использования, даже применительно к другому (иначе определенному) настраиваемому объекту. К сожалению, я не знаю, как сбросить запомненные свойства.

Eсть обходной путь: использовать Format-Table следующим образом. (Обратите внимание, что я добавил SizeGB отметить собственность в Get-VRamInfo для лучшего понимания.)

Function Get-DiskInfo {
$disk = Get-WMIObject Win32_Logicaldisk -ComputerName $computer |
            Select-Object  @{Name="Computer";Expression={$computer}}, 
                DeviceID,
                @{Name="SizeGB";Expression={$_.Size/1GB -as [int]}},
                @{Name="FreeGB";Expression={[math]::Round($_.Freespace/1GB,2)}}
        #Write-Host $Computer -ForegroundColor Magenta
        $disk
}

Function Get-VRamInfo {
$vram = Get-WmiObject win32_videocontroller -ComputerName $computer | 
            Select-Object @{Name="Computer";Expression={$computer}},
                @{Name="VideoRAM";Expression={$_.adapterram / 1MB -as [int]}},
                @{Name="SizeGB";Expression={$_.adapterram/1GB -as [int]}},
                Name
        #Write-Host $computer -ForegroundColor Cyan
        $vram
}

$computer = '.'
"`nshrunk output #1"
Get-VRamInfo
Get-DiskInfo
"`nfull output"
Get-VRamInfo | Format-Table
Get-DiskInfo | Format-Table
"`nshrunk output #2"
Get-DiskInfo
Get-VRamInfo

Вывод:

PS D:\PShell> D:\PShell\SF\884809.ps1

shrunk output #1

Computer VideoRAM SizeGB Name                 
-------- -------- ------ ----                 
.            2048      2 NVIDIA GeForce GT 740
.                    111                      
.                    932                      
.                      0                      

full output

Computer VideoRAM SizeGB Name                 
-------- -------- ------ ----                 
.            2048      2 NVIDIA GeForce GT 740


Computer DeviceID SizeGB FreeGB
-------- -------- ------ ------
.        C:          111  58.06
.        D:          932 856.47
.        E:            0      0

shrunk output #2

Computer DeviceID SizeGB FreeGB
-------- -------- ------ ------
.        C:          111  58.06
.        D:          932 856.47
.        E:            0      0
.                      2       

Write-Output командлет обычно используется в сценариях для отображения строк и других объектов на консоли. Однако, поскольку по умолчанию объекты отображаются в конце конвейера, обычно нет необходимости использовать командлет.
Например, Get-Process | Write-Output эквивалентно Get-Process.

Глядя на свои сценарии, вы не определяете $computer, поэтому он должен сразу же выполнить ошибку для любой из этих функций. После определения я могу подтвердить, что вторая функция просто отлично возвращает адаптеры при использовании в Windows 10 1703:

Как видно из вывода, $vram уже содержит ваше имя компьютера, поэтому вы можете пропустить Write-Host $Computer часть.

Как я вижу, вы, кажется, проверяете множество машин одновременно, вам имеет смысл взглянуть на рабочие процессы PowerShell, которые позволяют параллельное выполнение ваших задач, поэтому вы можете использовать свои функции в ForEach -Parallel цикл и заставить их выполняться намного быстрее.