Should i use [ValidateNotNullOrEmpty()] and then look for whitespace in the function, or use [ValidateScript(...)]?
Asked Answered
S

4

6

Because in PowerShell there is no

[ValidateNotNullOrWhiteSpace()]

Parameter attribute, is it better to use

[ValidateNotNullOrEmpty()]

as the parameter attribute, then look for whitespace inside the function, or should i use

[ValidateScript({ -not ([String]::IsNullOrWhiteSpace($_)) })]

as the parameter attribute.

im not sure what the NotNullOrEmpty attribute is really good for, because 99% of time, i don't want this to ever work:

My-Cmdlet -ParameterName " "

but because " " is still a string, it will pass the NotNullOrEmpty attribute.

Schliemann answered 27/4, 2015 at 19:6 Comment(1)
PowerShell 7.4 introduces [ValidateNotNullOrWhiteSpace] (github.com/MicrosoftDocs/PowerShell-Docs/pull/9664)Apologetics
L
9

The [ValidateNotNullOrEmpty()] is good for doing exactly what it says it will.

To answer your first question, I would use the [ValidateScript(...)] method you outlined.

One thing to keep in mind is that the error message for [ValidateScript()] is usually terrible and doesn't help the end user. As a workaround, you can do this:

[ValidateScript( { 
    ![String]::IsNullOrWhiteSpace($_) -or throw 'Your string is null or contains whitespace' 
} )]

You can also include an exception class in the throw like:

throw [System.ArgumentException]'Blah blah whitespace'

Why the -or throw syntax works

Boolean operators in PowerShell work like many other languages in that they do "shortcutting". They stop evaluating the expression as soon as the outcome is definite. So for $false -and $(sleep -min 10) it doesn't take 10 minutes, because the second expr is never evaluated.

Similarly, $true -or $(something) will not evaluate the second, because it will always be true if the first expression is true.

So in this case it's similar. ValidateScript needs a bool. If the condition we care about is true, it will stop there. If it's not, the second expression is evaluated, and since that's a throw it will just fail, but in this case you can control the failure message (and exception class if you want).

Lasko answered 27/4, 2015 at 19:18 Comment(3)
I'm getting "You must provide a value expression following the '-or' operator." in PowerShell Core 7.4.1 inside VS Code. I like the concise format but I had to switch to @RoadRunner's syntax.Milligram
@JeffHumphreys thanks, I think you need to wrap the throw in () or $()`, if that works then I will edit the answerLasko
Thanks @RoadRunner, I tried (), $(), ${}, {}. I thought it might be an issue with PowerShell Extension VS Code, so I tried the ISE with PS 5, and the PS 7 console, different errors but no luck. function Test-ValidateScriptThrow{ param( [ValidateScript( { ![String]::IsNullOrWhiteSpace($_) -or (throw 'Your string is null or contains whitespace') } )] ) }Milligram
P
2

An easy workaround would be to just Trim() the whitespace and call [string]::IsNullOrEmpty() inside [ValidateScript()]:

[ValidateScript({
    if ([string]::IsNullOrEmpty($_.Trim()))
    {
        throw "Your string is null or empty."
    } else {
        $true
    }
})]

Which will handle all $null, "" and " " cases, since all whitespace " " will just be converted to "".

Proserpina answered 27/3, 2020 at 1:57 Comment(0)
C
2

With at least PowerShell 7.2 and newer you can set a ErrorMessage value on a ValidateScript attribute.

  [ValidateScript(
    {![String]::IsNullOrWhiteSpace($_)},
    ErrorMessage = “null or whitespace”
  )]

More info on Microsoft Learn

Centillion answered 12/3, 2024 at 4:34 Comment(0)
P
0

You can make your own ValidateNotNullOrWhiteSpace attribute, even in Windows PowerShell 5.1, you just need to create a Class that inherits from ValidateEnumeratedArgumentsAttribute.

using namespace System.Management.Automation

class ValidateNotNullOrWhiteSpace : ValidateEnumeratedArgumentsAttribute {
    [void] ValidateElement([Object] $element) {
        if (-not [string]::IsNullOrWhiteSpace($element)) {
            return
        }

        throw [System.Management.Automation.MetadataException]::new(
            'The argument is null, empty, or consists of only white-space characters. ' +
            'Provide an argument that contains non white-space characters, and then try the command again.')
    }
}

function Test-Attribute {
    param([ValidateNotNullOrWhiteSpace()] $foo)
}

Test-Attribute '   '
Phosphoprotein answered 12/3, 2024 at 4:54 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.