Выход PowerShell пересекается между функциями
Я пишу сценарий PowerShell в версии 5.1 для Windows 10, который получает определенные фрагменты информации о локальной системе (и в конечном итоге о ее подсетях) и выводит их в текстовый файл. Сначала у меня были все аспекты в одной функции. Я столкнулся с проблемами вывода при выводе getUsersAndGroups
а также getRunningProcesses
функции, где вывод из getUsersAndGroups
будет введен в вывод getRunningProcesses
,
Две функции:
# Powershell script to get various properties and output to a text file
Function getRunningProcesses()
{
# Running processes
Write-Host "Running Processes:
------------ START PROCESS LIST ------------
"
Get-Process | Select-Object name,fileversion,productversion,company
Write-Host "
------------- END PROCESS LIST -------------
"
}
Function getUsersAndGroups()
{
# Get Users and Groups
Write-Host "Users and Groups:"
$adsi = [ADSI]"WinNT://$env:COMPUTERNAME"
$adsi.Children | where {$_.SchemaClassName -eq 'user'} | Foreach-Object {
$groups = $_.Groups() | Foreach-Object {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
$_ | Select-Object @{n='Username';e={$_.Name}},@{n='Group';e={$groups -join ';'}}
}
}
getRunningProcesses
getUsersAndGroups
Когда я звоню getUsersAndGroups
после getRunningProcesses
, вывод выглядит так (не выводит getUsersAndGroups
совсем):
Running Processes:
------------ START PROCESS LIST ------------
Name FileVersion ProductVersion Company
---- ----------- -------------- -------
armsvc
aswidsagenta
audiodg
AVGSvc
avgsvca
avguix 1.182.2.64574 1.182.2.64574 AVG Technologies CZ, s.r.o.
conhost 10.0.14393.0 (rs1_release.160715-1616) 10.0.14393.0 Microsoft Corporation
csrss
csrss
dasHost
dwm
explorer 10.0.14393.0 (rs1_release.160715-1616) 10.0.14393.0 Microsoft Corporation
hkcmd 8.15.10.2900 8.15.10.2900 Intel Corporation
Idle
igfxpers 8.15.10.2900 8.15.10.2900 Intel Corporation
lsass
MBAMService
mDNSResponder
Memory Compression
powershell_ise 10.0.14393.103 (rs1_release_inmarket.160819-1924) 10.0.14393.103 Microsoft Corporation
RuntimeBroker 10.0.14393.0 (rs1_release.160715-1616) 10.0.14393.0 Microsoft Corporation
SearchFilterHost
SearchIndexer
SearchProtocolHost
SearchUI 10.0.14393.953 (rs1_release_inmarket.170303-1614) 10.0.14393.953 Microsoft Corporation
services
ShellExperienceHost 10.0.14393.447 (rs1_release_inmarket.161102-0100) 10.0.14393.447 Microsoft Corporation
sihost 10.0.14393.0 (rs1_release.160715-1616) 10.0.14393.0 Microsoft Corporation
smss
spoolsv
sqlwriter
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost
svchost 10.0.14393.0 (rs1_release.160715-1616) 10.0.14393.0 Microsoft Corporation
System
taskhostw 10.0.14393.0 (rs1_release.160715-1616) 10.0.14393.0 Microsoft Corporation
ToolbarUpdater
wininit
winlogon
WtuSystemSupport
WUDFHost
------------ END PROCESS LIST ------------
Users and Groups:
Когда я звоню getUsersAndGroups
до getRunningProcesses
выход getUsersAndGroups
вводится в getRunningProcesses
и что еще хуже, в списке нет ни одного запущенного процесса, а много пустых строк.
Как я могу отделить или контролировать вывод getUsersAndGroups
так что он выводит до выхода getRunningProcesses
?
Вывод введенного вывода выглядит так:
Running Processes:
------------ START PROCESS LIST ------------
Username Group
-------- -----
Administrator Administrators
debug255 Administrators;Hyper-V Administrators;Performance Log Users
DefaultAccount System Managed Accounts Group
Guest Guests
------------ END PROCESS LIST ------------
Спасибо большое за вашу помощь!
1 ответ
ТЛ; др:
Принудительно вывести синхронный вывод на консоль с помощью явного командлета форматирования:
getUsersAndGroups | Format-Table
getRunningProcesses | Format-Table
Обратите внимание, что это, прежде всего, проблема с отображением, и вам не нужен этот обходной путь для захвата вывода в файл или его передачи по конвейеру.
Полезно продемонстрировать проблему с MCVE (минимальный, полный и проверяемый пример):
Write-Host "-- before"
[pscustomobject] @{ one = 1; two = 2; three = 3 }
Write-Host "-- after"
В PSv5+ это дает:
-- before
-- after
one two three
--- --- -----
1 2 3
Что случилось?
Write-Host
звонки производятся синхронно.- Стоит отметить, что
Write-Host
обходит нормальный поток вывода успеха и (по сути) записывает напрямую в консоль - в основном, даже если есть законное использование,Write-Host
следует избегать
- Стоит отметить, что
Неявный вывод - не захватывая вывод из оператора
[pscustomobject] @{ one = 1; two = 2; three = 3 }
- был неожиданно не синхронным:- Пустая строка была первоначально произведена.
- Весь фактический результат последовал за финалом
Write-Host
вызов.
Этот полезный ответ объясняет, почему это происходит; короче:
Неявный вывод форматируется в зависимости от типа выводимых объектов; в данном случае,
Format-Table
неявно используется.В Psv5 +, неявно применяется
Format-Table
сейчас ждет до 300 мсек. чтобы определить подходящую ширину столбца.К сожалению, это означает, что последующие команды выполняются внутри этого временного окна и могут производить несвязанные выходные данные (посредством обходных конвейерных команд, таких как
Write-Host
) или запросить ввод пользователя передFormat-Table
выход начинается.
Примечание: этот ответ изначально неправильно "обвинял" PSv5+ 300 мсек. задержка для потенциально неожиданного стандартного поведения форматирования вывода (то, что первый объект, отправленный в конвейер, определяет формат отображения для всех объектов в конвейере - см. мой ответ).