Подавление и обработка вывода ошибок stderr в сценарии PowerShell

Я хотел захватить общие ресурсы SMB с помощью PowerShell, но это не работает

# Cannot use CIM as it throws up WinRM errors.
# Could maybe use if WinRM is configured on all clients, but this is not a given.
$cim = New-CimSession -ComputerName $hostname
$sharescim = Get-SmbShare -CimSession $cim

Так что это привело меня к другому методу с использованием сетевого представления, и это вполне нормально, если хостом является Windows.

# This method uses net view to collect the share names (including hidden shares like C$) into an array
# https://www.itprotoday.com/powershell/view-all-shares-remote-machine-powershell
try { $netview = $(net view \\$hostname /all) | select -Skip 7 | ?{$_ -match 'disk*'} | %{$_ -match '^(.+?)\s+Disk*'|out-null ; $matches[1]} }
catch { $netview = "No shares found" }

Итак, если хостом является Linux, я получаю сообщение об ошибке, и, как вы можете видеть, выше я пытаюсь подавить эту ошибку с помощью try/catch, но это не удается.

Очевидно, это связано с тем, что «net view» является CMD, поэтому его нельзя контролировать с помощью try/catch. Итак, мой вопрос: как я могу а) подавить системную ошибку ниже? и б) обработать эту ошибку, когда она произойдет (т.е. выдать этот хост не отвечает на 'net view' или что-то взамен ошибки)?

System error 53 has occurred.
The network path was not found.

person YorSubs    schedule 04.10.2020    source источник
comment
Кстати: вам не нужно $(...) запускать внешнюю программу; короче: $(...) требуется только в расширяемых строках ("...") или для встраивания целых операторов в другие операторы.   -  person mklement0    schedule 04.10.2020
comment
Еще одно замечание: net.exe — это консольное приложение, и поэтому оно не связано с какой-либо конкретной оболочкой. Как консольное приложение, оно имеет в своем распоряжении только два потока вывода: stdout (стандартный вывод) для данных и stderr (стандартная ошибка) для сообщений об ошибках и/или сообщений о состоянии.   -  person mklement0    schedule 04.10.2020


Ответы (1)


Вывод Stderr (стандартная ошибка) из внешних программ не интегрирован с обработкой ошибок PowerShell, прежде всего потому, что этот поток используется не только для сообщения ошибок, но и информацию об статусе.
(Поэтому вы должны делать выводы об успехе или неудаче вызова внешней программы только по ее коду выхода, как показано в $LASTEXTICODE[1]).

Однако вы можете перенаправить вывод stderr, и перенаправление на $null (2>$null) отключит его[2]:

$netview = net view \\$hostname /all 2>$null | ...
if (-not $netview) { $netview = 'No shares found' }

[1] Действия с ненулевым кодом выхода, который по соглашению сигнализирует об ошибке, также не интегрированы в обработку ошибок PowerShell начиная с версии 7.1, но исправление предлагается в этот RFC.

[2] Вплоть до PowerShell 7.0 любое перенаправление 2> неожиданно также записывает строки stderr в автоматическую коллекцию $Error. Эта проблема была исправлена ​​в версии 7.1
В качестве нежелательного побочного эффекта в версиях до версии 7.0 перенаправление 2> также может вызывать ошибку завершения сценария, если действует $ErrorActionPreference = 'Stop', если хотя бы один выдается строка stderr.

person mklement0    schedule 04.10.2020