3

I am writing a Chef library to make writing a custom resource for managing Microsoft MSMQ resources on Windows Server easier. Chef interfaces with Windows using Powershell 5.1.

I want to raise an error if my call to Get-MsmqQueue fails and returns $Null. To do so, I have created a filter to raise an error if the value is invalid. This seems to work if I pipeline a $Null value, but if the value is returned from Get-MsmqQueue and is $Null, it does not work.

Does anybody have an idea why line #5 does not raise an error, even if the value is equal to $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
  • Functions in pipelines can be tricky. mcpmag Commented Mar 3, 2020 at 21:59
  • That filter can be false with a 0 or empty string. Here's another example: $a = cmd /c 'echo hi | find "there"' Commented Mar 3, 2020 at 22:06

2 Answers 2

5

A cmdlet that produces no output doesn't actually emit $null - it (implicitly) emits the [System.Management.Automation.Internal.AutomationNull]::Value singleton that in expressions acts like $null, but in enumeration contexts such as the pipeline enumerates nothing and therefore sends nothing through the pipeline - unlike an actual $null value.

# 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

As of PowerShell 7.0, [System.Management.Automation.Internal.AutomationNull]::Value can only be discovered indirectly, using obscure techniques such as the following:

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

This lack of discoverability is problematic, and improving the situation by enabling the following is the subject of this GitHub proposal.

$var -is [AutomationNull] # WISHFUL THINKING as of PowerShell 7.0
Sign up to request clarification or add additional context in comments.

Comments

0

A different way to test it. This tests the standard output being non-null, not the exit code. I'm not testing the equality. The assignment is a side effect.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.