Фильтр Powershell игнорируется в трубопроводе - PullRequest
2 голосов
/ 04 марта 2020

Я пишу библиотеку Chef, чтобы упростить написание пользовательского ресурса для управления ресурсами Microsoft MSMQ на Windows Сервере. Chef взаимодействует с Windows с помощью Powershell 5.1.

Я хочу вызвать ошибку, если мой вызов на Get-MsmqQueue завершится неудачно и вернет $Null. Для этого я создал фильтр, чтобы вызвать ошибку, если значение недопустимо. Это похоже на работу, если я передаю значение $Null, но если значение возвращается из Get-MsmqQueue и равно $Null, оно не работает.

Кто-нибудь имеет представление, почему строка № 5 не вызывает ошибку, даже если значение равно $Null?

#1 filter Test-Null{ if ($Null -ne $_) { $_ } else { Write-Error "object does not exist" }}

#2 $a = $Null
#3 $a | Test-Null | ConvertTo-Json     # this raises an error

#4 $a = Get-MsmqQueue -Name DoesNotExist
#5 $a | Test-Null | ConvertTo-Json     # this does NOT raise an error
#6 $Null -eq $a                        # this evaluates to $True

Ответы [ 2 ]

3 голосов
/ 04 марта 2020

Командлет, который создает no , на самом деле не генерирует $null - он (неявно) испускает [System.Management.Automation.Internal.AutomationNull]::Value singleton , который в выражениях действует подобно $null, но в контекстах перечисления , таких как конвейер, перечисляет ничто и, следовательно, ничего не отправляет через конвейер - в отличие от фактического $null значение.

# True $null *is* sent through the pipeline.
PS> $var = $null; $var | ForEach-Object { 'here' }
here 

# [System.Management.Automation.Internal.AutomationNull]::Value is *not*.
# `& {}` is a simple way to create this value.
PS> $var = & {}; $var | ForEach-Object { 'here' }
# !! No output

Начиная с PowerShell 7.0, [System.Management.Automation.Internal.AutomationNull]::Value можно обнаружить только косвенно , используя скрытые методы такие следующим образом:

# Only returns $true if $var contains
# [System.Management.Automation.Internal.AutomationNull]::Value
$null -eq $var -and @($var).Count -eq 0

Это отсутствие обнаруживаемости проблематично c, и улучшение ситуации путем включения следующего является предметом этого предложения GitHub .

$var -is [AutomationNull] # WISHFUL THINKING as of PowerShell 7.0
0 голосов
/ 05 марта 2020

Другой способ проверить это. Это проверяет, что стандартный вывод не нулевой, а не код выхода. Я не проверяю равенство. Назначение является побочным эффектом.

if (not ($a = Get-MsmqQueue -Name DoesNotExist)) { 
  Write-Error "object does not exist" }
...