#Param validation

11 messages · Page 1 of 1 (latest)

worldly ocean
#

I'm looking to validate some file paths if passed in to the script and I was wondering which is the preferred/cleanest in order to level up my scripting?

In the process block?

    # Validate the csvPath parameter is a valid path and ends with a trailing slash
    if ($PSBoundParameters.ContainsKey('csvPath')) {
        try {
            Test-Path -Path $csvPath -PathType Container 
        }
        catch {
            throw "The path defined in $csvPath is not valid.  An example of a working path is C:\temp\"
        }
        if (-not $csvPath.EndsWith("\")) {
            $csvPath += "\"
        } 
    }

or is it better in the param declaration itself?

    [Parameter(Position=2, 
    Mandatory=$false, 
    ValueFromPipeline=$true, 
    ValueFromPipelineByPropertyName=$true,
    HelpMessage="Desired full path for output, a valid path looks like C:\temp\")]
    [ValidateScript( {
        if (-not (Test-Path -Path $_ -PathType Container)) {
            throw "The path defined in $_ is not valid. An example of a working path is C:\temp\"
        }
        if (-not $_.EndsWith("\")) {
            $_ += "\"
        }
        return $_
    })]
    [string]$csvPath = "$(Get-Location)\"

Or is there an even better way I should look for?

uncut cairn
#

In the param block

worldly ocean
#

thanks, I saw it in the documentation but I've never seen one in someone else's so I wasn't sure if I was hallucinating lol

mental moon
#

Naw, param block is the best place for validation.
I could go wild on a tangent on just why but simply put, it's the earliest you can fail your script and the sooner you fail, the less time gets wasted and the less things get unnecessarily modified/connected to/etc.

Also: Don't try to force people to append a \ - instead, later on, use Join-Path to combine folder with file-name for the full path. A lot less vulnerable that way 🙂
110% unbiased opinion: If you use the module PSFramework there are alternatives available to make validation easier. Definitely not brining that up because I'm the author 😉

worldly ocean
mental moon
#

Yeah, that one is really some docs I need to pick up (but of no interest to you - that article is supposed to cover how to use PSFramework from within C#).
Sec, let me grab the examples link for what I had in mind ...

#

A type for single directories is going to be in the next release, but ... well, that's not going to be tomorrow.
If you prefer to stick with string - simple, reliable ad only a single path - then this could be it:

param (
    [PSFValidateScript('PSFramework.Validate.FSPath.Folder', ErrorString = 'PSFramework.Validate.FSPath.Folder')]
    [string]
    $CsvPath
)
worldly ocean
#

thanks for the pointers, I'll play around with things. also I had to move the '' to the process anyways since it seems that validatescript only looks for $true to be returned.

mental moon
#

In all cases, there's one issue you'll have to keep in mind (but there is a simple solution for):
There is no automatic module import for types.
If you don't do anything and launch the script without first importing PSFramework, it is going to fail right away (unknown type).
To solve that - and in general a good idea for scripts - you can include a module requirement at the very top of your file:

#requires -Modules PSFramework

This will automatically import all required modules before param binding. Also helps fail the script fast (and with a good error) if a required module is missing.

#

On the note of modifying the input path:
This is bad:

$exportPath = $CsvPath + 'export.csv'

Do this instead:

$exportPath = Join-Path -Path $CsvPath -ChildPath 'export.csv'

That way you don't have to worry about puzzling together slashes just right. It also puts them in the right direction depending on OS 🙂