Я пишу большой скрипт, который сканирует информацию 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
цикл и заставить их выполняться намного быстрее.