Validating parameter set using data from XML file

This topic contains 2 replies, has 3 voices, and was last updated by  Curtis Smith 2 weeks, 4 days ago.

  • Author
    Posts
  • #76141

    Eric
    Participant

    Hello all,

    I am trying to set up a function that validates a parameter entry based on data from an XML file.

    The XML file is set up something like this:

    Dev1
    OU=People,DC=Dev1,DC=org
    OU=Computers,DC=Dev1,DC=org

    Stage1
    OU=People,DC=Stage1,DC=org
    OU=Computers,DC=Stage1,DC=org

    There is a parameter set up in the function $OU and I want the ValidateSet to be any of the four OUs from the XML file.

    I've tried just putting the code to read form the XML straight into the ValidateSet, but it gives me an error saying it must be a string or code block.
    I've tried using a ValidateScript, but I could not find any references on how to search for NodeNames where the node -contains "OU".

    I've also seen some people have tried to use an enum, but this fails too because I don't think it likes the commas in the DNs.
    I'm not sure if adding any of my code would be of any help since none of it has worked so far 🙂

    Any guidance would be very appreciated as I am trying to get this code to be environment agnostic. Just move the scripts over to a new environment, make changes to the config file and away we go.

    Thanks,

    Eric

  • #76184

    Don Jones
    Keymaster

    Yeah, the Param() block can't contain code... except in a ValidateScript(). And you can't really use -contains against an XML data source per se; that's not what the -contains operator means. You'd have to read in the XML and work out the logic to pull your valid values into a collection of strings, and then use -in or -contains against that.

    But you're really going a bit beyond what the validation parameters are meant to do; they're not quite envisioned as being _that_ dynamic, and you don't really get an advantage in this case. For example, having the data source path hardcoded in really breaks the native pattern of function input points, and creates an external dependency that someone has to "just know" to manage.

    I'd probably create a mandatory parameter that provided the XML data file path – so that it's apparent to anyone using the command that a data file is indeed needed and expected. You could default that to something sensible, instead of making it mandatory – it still serves as "documentation" that way. And then just validate the values in the main code, rather than using a validation attribute.

  • #76190

    Curtis Smith
    Participant

    I agree with Don's points, but also like to see if I can accomplish the challenge. Here is what I came up with.

    First the data provided in the original post is not XML (the XML elements may have been stripped by the forum)
    Here is the XML I used for the example.

    and here is an example of how I used ValidateScript with the XML file

    Param(
        [string]$validationfile = "validation.xml",
    
        [ValidateScript({(Import-Clixml $validationfile).name -contains $_})]
        [string]$set
    )
    "The set: $set exists in the XML"

    When -set is defined with a valid value, the result is the execution of the code:

    PS D:\temp> .\testval.ps1 -set Dev
    The set: Dev exists in the XML

    When -set was defined with an invalid value, the result is and error being thrown for the validation failing:

    PS D:\temp> .\testval.ps1 -set Dev1
    D:\temp\testval.ps1 : Cannot validate argument on parameter 'set'. The "(Import-Clixml $validationfile).name -contains $_" validation script for the argument with value "Dev1" did not return a result of True. Determine why the validation script failed, and 
    then try the command again.
    At line:1 char:20
    + .\testval.ps1 -set Dev1
    +                    ~~~~
        + CategoryInfo          : InvalidData: (:) [testval.ps1], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationError,testval.ps1
     

You must be logged in to reply to this topic.