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

#powershell #networking #ip #stderr #smb

#powershell #сеть #ip #stderr #smb

Вопрос:

Я хотел захватить общие ресурсы 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
  

Итак, это привело меня к другому методу с использованием net view, и это вполне нормально, если хост — 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.
  

Комментарии:

1. В качестве отступления: вам не нужно $(...) запускать внешнюю программу; короче говоря: $(...) требуется только в расширяемых строках ( "..." ) или для встраивания целых операторов в другие операторы.

2. Еще один аспект: net.exe это консольное приложение и, как таковое, не связано с какой-либо конкретной оболочкой. Как консольное приложение, оно имеет в своем распоряжении только два выходных потока: stdout (стандартный вывод) для данных и stderr (стандартная ошибка) для сообщений об ошибках и / или сообщений о состоянии.

Ответ №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.1.x любое 2> перенаправление неожиданно также записывает строки stderr в автоматическую $Error коллекцию. Эта проблема была исправлена в версии 7.1
как неприятный побочный эффект, в версиях до версии 7.0 2> перенаправление может также выдавать ошибку завершения сценария $ErrorActionPreference = 'Stop' , если она имеет место, если выдается хотя бы одна строка stderr.