function Test-Mystery { [CmdletBinding()] param ( [ValidateNotNullOrEmpty()] $paramOne ) $paramOne $paramOne.length }Pretty straightforward advanced function stuff, we have a parameter that we need to validate. It can be anything it wants as long as it’s not null, and is not an empty string. If we test this, we’ll find that it works. Mostly.
PS > $x = "HELLO WORLD"
PS > Test-Mystery -paramOne $x
HELLO WORLD
11
PS > $x = ""
PS > Test-Mystery -paramOne $x
Test-Mystery : Cannot validate argument on parameter 'paramOne'. The argument is null or empty. Supply an argument that is not null or empty and then try the command again.
At line:2 char:23
+ Test-Mystery -paramOne <<<< $x
+ CategoryInfo : InvalidData: (:) [Test-Mystery], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Test-Mystery
Okay, that works as expected. But let’s try that with input from the Read-Host cmdlet. First we’ll enter in a string, then we’ll just hit Enter to return nothing (in theory).
PS > $x = Read-Host "Test "
PS > Test-Mystery -paramOne $x
Test: HELLO WORLD
HELLO WORLD
11
PS > $x = Read-Host "Test "
PS > Test-Mystery -paramOne $x
Test:
0
Uhh….what? That totally should have exploded, and yet it doesn’t. Adding to the mystery is that the variable being assigned the return value from Read-Host is indeed a [System.String] variable and it is assigned the value of ‘’ (or an empty string). At least that’s what PSDebug tells us:
PS > $x = read-host 'test '
DEBUG: 1+ $x = <<<< read-host 'test '
test :
DEBUG: ! SET $x = ''.
PS > $x.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ------ --------
True True String System.Object
PS > $x –eq “”
True
And so thus is given to us the mystery: when is an empty string not an empty string? Evidently, when it’s created by Read-Host. But, thankfully there is a fairly straight forward solution. We strongly type the variable being assigned the output from Read-Host.
PS > [string]$x = Read-Host 'Test '
Test :
PS > Test-Mystery $x
Test-Mystery : Cannot validate argument on parameter 'paramOne'. The argument is null or empty. Supply an argument that is not null or empty and then try the command again.
At line:2 char:13
+ Test-Mystery <<<< $x
+ CategoryInfo : InvalidData: (:) [Test-Mystery], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Test-Mystery
I’ll pose this question on the PowerShell Technet Forums, and see if it this is ‘as designed’ or a genuine bug that we need to file on Connect. Until then, case (almost) closed.