PS7.1 - Как вы используете конвейерную цепочку с пользовательскими функциями? - PullRequest
2 голосов
/ 19 июня 2020

Согласно документации, PS 7 представила операторы цепочки конвейеров, такие как || и &&. https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_pipeline_chain_operators?view=powershell-7

И вы должны иметь возможность выполнять операции короткого замыкания в стиле C#, например:

Write-Error 'Bad' && Write-Output 'Second'

Приведенные выше примеры работай. И в документации говорится, что операторы цепочки конвейера используют два поля (не знаю, как это работает точно): $? и $LASTEXITCODE

Как мне применить их к моим собственным функциям?

Для пример:

function yes() { 
  echo 'called yes'
  return $True 
}
function no() { 
  echo 'called no'
  return $False 
}

Я чувствую, что смогу запустить следующий no && yes и увидеть следующий результат

с именем no

False

но вместо этого я вижу

вызвано нет

ложно

вызвано да

верно

Итак, как мне разработать функции таким образом, чтобы я мог использовать цепочку конвейеров и короткое замыкание? && означает throw, но это не кажется слишком полезным в общем случае.

1 Ответ

1 голос
/ 19 июня 2020

&& и || работают только с успешным статусом команды, что отражено в automati c $? переменная (как вы указываете) - что не связано с тем, что команда выводит (возвращает).

Функции и скрипты сообщают $? как $true, если не было предпринято явных действий; то есть, даже если команды, используемые внутри скрипта / функции, терпят неудачу, $? по-прежнему $true при выходе из скрипта / функции.

К сожалению, в PowerShell 7.0 прямого пути нет для функции , чтобы напрямую установить $? на $false, хотя планируется добавить такую ​​функцию - см. в этом GitHub .

В сценарии использование exit с ненулевым кодом выхода, однако, эффективно (это приводит к тому, что $LASTEXITCODE отражает код выхода, а механизм PowerShell устанавливает $? на $false, если код выхода отличен от нуля - это также то, как это работает, когда вы вызываете внешние программы ).


На данный момент существует только следующий неоптимальный обходной путь для функций; он субоптимален в том смысле, что неизменно выдает сообщение об ошибке :

function no { 
  # Make the function an advanced one, so that $PSCmdlet.WriteError()
  # can be called.
  [CmdletBinding()]
  param()

  # Call $PSCmdlet.WriteError() with a dummy error, which
  # sets $? to $false in the caller's scope.
  # By default, this dummy error prints and is recorded in the $Error
  # collection; you can use -ErrorAction Ignore on invocation to suppress
  # that.
  $PSCmdlet.WriteError(
   [System.Management.Automation.ErrorRecord]::new(
     [exception]::new(), # the underlying exception
     'dummy',            # the error ID
     'NotSpecified',     # the error category
     $null)              # the object the error relates to
  ) 
}

Функция no теперь устанавливает $? в false, что вызывает ветвь ||; -EA Ignore (-ErrorAction Ignore) используется для отключения фиктивной ошибки.

PS> no -EA Ignore || 'no!'
no!
...