Обратите внимание, что интересующее поведение применяется , как правило, к командам PowerShell , а не только в контексте Invoke-Command
и - , как правило, которых следует избегать - Invoke-Expression
; в вашем случае нужно только обойти ошибку . [1]
Ваш собственный ответ показывает, как перенаправить один специфицирует c выходных потоков в поток вывода успеха ; Например, 3>&1
перенаправляет (>&
) поток предупреждения (3
) в поток успеха (вывода) (1
).
&
указывает, что целью перенаправления является поток , в отличие от файла ; для получения дополнительной информации о выходном потоке PowerShell см. about_Redirection
.
Если вы хотите перенаправить все выходных потоков в поток вывода успеха используйте перенаправление *>&1
Путем перенаправления всех потоков в выходной поток их объединенный вывод может быть записан в переменную, перенаправлен в файл или отправлен через конвейер , тогда как по умолчанию захватывается только выходной поток success (1
).
Отдельно , вы можете использовать общие параметры именованные -*Variable
параметры для захвата выходных данных отдельного потока в переменных для некоторых потоков, а именно:
- Поток
1
(успех): -OutVariable
- Поток
2
(ошибка): -ErrorVariable
- Поток
3
(предупреждение): -WarningVariable
- Поток
6
(информация): -InformationVariable
Обязательно указывайте целевую переменную только имя , без $
префикс ; например, для захвата предупреждений в переменной $warnings
используйте
-WarningVariable warnings
, например, в следующем примере:
Write-Warning hi -WarningVariable warnings; "warnings: $warnings"
Обратите внимание, что с -*Variable
выходные данные потока собираются в переменную независимо от того, отключите ли вы этот поток или даже игнорируете его в противном случае , с заметным исключением 1113 *, в этом случае -ErrorVariable
переменная не заполнена (и ошибка также не записана в automati c $Error
переменная , которая в противном случае записывает все ошибки, которые происходят в сессия).
Как правило, -{StreamName}Action SilentlyIgnore
представляется эквивалентным {StreamNumber}>$null
.
Обратите внимание на отсутствие многословия (4
) и потоки отладки (5
) выше; вы можете только захватить их косвенно , через 4>&1
и 5>&1
(или *>&1
), что затем требует от вас извлечения интересующего результата из объединенного поток через фильтрацию по выходному объекту тип :
Важно :
Подробное (4
) и потоки отладки (5
) - это единственные два потока, тихие в источнике по умолчанию ; то есть , если только эти потоки явно не включены через -Verbose
/ -Debug
или их переменную предпочтения эквивалентов, $VerbosePreference = 'Continue'
/ $DebugPreference = 'Continue'
, ничего не является испускается и ничего не может быть захвачено .
Информационный поток (5
) равен только без звука на выходе по умолчанию ; то есть запись в информационный поток (с Write-Information
) всегда записывает объекты в поток, но они не отображаются по умолчанию (они отображаются только с -InformationAction Continue
/ $InformationPreference = 'Continue'
)
- Начиная с версии 5,
Write-Host
теперь тоже записывает в информационный поток, хотя его вывод выводит по умолчанию, но можно подавить с помощью 6>$null
или -InformationAction Ignore
(но не -InformationAction SilentlyContinue
).
# Sample function that produces success and verbose output.
# Note that -Verbose is required for the message to actually be emitted.
function foo { Write-Output 1; Write-Verbose -Verbose 4 }
# Get combined output, via 4>&1
$combinedOut = foo 4>&1
# Extract the verbose-stream output records (objects).
# For the debug output stream (5), the object type is
# [System.Management.Automation.DebugRecord]
$verboseOut = $combinedOut.Where({ $_ -is [System.Management.Automation.VerboseRecord] })
[1] Ошибка захвата потока, начиная с PowerShell v7.0:
В двух словах: В контексте удаленное взаимодействие (например, Invoke-Command -Session
здесь), фоновые задания и так называемые миниоболочки (передача блока сценария в CLI PowerShell для выполнения команд в дочернем процессе), только ожидаемые (1
) и ошибочные (2
) потоки могут быть перехвачены, как и ожидалось ; все остальные неожиданно передаются на хост (дисплей) - см. эту проблему GitHub .
Ваша команда должна - но в настоящее время не работает - работает следующим образом, что избавило бы от необходимости Invoke-Expression
:
# !! 3>&1 redirection is BROKEN as of PowerShell 7.0, if *remoting* is involved
# !! (parameters -Session or -ComputerName).
$RemoteOutput =
Invoke-Command -Session $Session $Commands 3>&1 -ErrorVariable RemoteError 2>$null
То есть, в принципе, вы должны иметь возможность передавать переменную $Commands
, которая содержит блок скрипта, непосредственно как (подразумеваемый) аргумент -ScriptBlock
до Invoke-Command
.