Home > Enterprise >  Create a powershell function that validates a username with regex ValidatePattern but can't s
Create a powershell function that validates a username with regex ValidatePattern but can't s

Time:09-21

I'm trying to create a powershell function that validates users names and if a tech inputs the wrong character, I want it to throw an error message as to why it was wrong and restart the script for them to make the choice again.

So far I have this

Running VSCode with Powershell Extension 2022.8.5

function stringTest {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [ValidateLength(4,15)]
        [ValidatePattern('^[a-zA-Z0-9-_] $')]
        [string] $alphaTest 
        
    )
        Write-Host $alphaTest
}

$writeHere = Read-Host "UserName: "

stringTest($writeHere)

Output:

UserName: doej

doej

This works fine, but I want to try and add Custom error messages using the ErrorMessage within Validate Pattern. So I would try this

function stringTest {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [ValidateLength(4,15)]
        [ValidatePattern({$pattern = "^[a-zA-Z0-9-_] $([Regex]::escape($pattern))\s"
        if ($_ -in $pattern ) {return $true}
        throw "$_ is not a valid character. Valid characters are: '$($pattern -join ',')'"
    })]
        [string] $alphaTest 
        
    )
        Write-Host $alphaTest
}

$writeHere = Read-Host "UserName: "

stringTest($writeHere)

But now my Validate doesn't actually validate anymore? I try the same name or anything different that "should" be valid

Cannot validate argument on parameter 'alphaTest'. The argument "doej" does not match the "$pattern = | "^[a-zA-Z0-9-] $([Regex]::escape($pattern))\s" if ($ -in $pattern ) {return $true} throw "$_ is not a valid | character. Valid characters are: '$($pattern -join ',')'" " pattern. Supply an argument that matches "$pattern = | "^[a-zA-Z0-9-] $([Regex]::escape($pattern))\s" if ($ -in $pattern ) {return $true} throw "$_ is not a valid | character. Valid characters are: '$($pattern -join ',')'" " and try the command again.

From the looks of it, it's trying to match the regex pattern exactly instead of working the way before. Any help would be greatly appreciated or pointing me in the write direction for this.

CodePudding user response:

You can have your custom attribute declaration using a class as described in this answer, both ValidatePattern and ValidateLength attribute declarations inherit from the same base class, ValidateArgumentsAttribute Class.

You can also use ValidateScript as described in mklement0's answer.

Here is one example of how the custom class would look like:

class ValidateCustomAttribute : Management.Automation.ValidateEnumeratedArgumentsAttribute {
    hidden [int] $Min
    hidden [int] $Max
    hidden [string] $Pattern

    ValidateCustomAttribute() { }
    ValidateCustomAttribute([scriptblock] $Validation) {
        $this.Min, $this.Max, $this.Pattern = & $Validation
    }

    [void] ValidateElement([object] $Element) {
        if($Element.Length -lt $this.Min -or $Element.Length -gt $this.Max) {
            $errorRecord = [Management.Automation.ErrorRecord]::new(
                [Exception] ('Invalid Length! Must be between {0} and {1}.' -f $this.Min, $this.Max),
                'InvalidLength',
                [Management.Automation.ErrorCategory]::InvalidArgument,
                $Element
            )
            throw $errorRecord
        }
        if($Element -notmatch $this.Pattern) {
            $errorRecord = [Management.Automation.ErrorRecord]::new(
                [Exception] ('Invalid Argument! Does not match {0}.' -f $this.Pattern),
                'PatternNotMatch',
                [Management.Automation.ErrorCategory]::InvalidArgument,
                $Element
            )
            throw $errorRecord
        }
    }
}

As for the implementation:

function Test-Attribute {
    param(
        [ValidateCustomAttribute({ 2, 10, '^[a-zA-Z0-9-_] $' })]
        [object] $Test
    )

    $Test
}

This syntax is also valid for the attribute declaration:

[ValidateCustomAttribute(Min = 2, Max = 10, Pattern = '^[a-zA-Z0-9-_] $')]

And the testing:

PS /> Test-Attribute 'hello???'
Cannot validate argument on parameter 'Test'. Invalid Argument! Does not match ^[a-zA-Z0-9-_] $.

PS /> Test-Attribute 'somelongstring'
Cannot validate argument on parameter 'Test'. Invalid Length! Must be between 2 and 10.

PS /> Test-Attribute hello
hello

As aside, the pattern can be reduced to just ^[\w-] $.

  • Related