#PowerShell, #PowerWiseScripting, #ProjectWise, PWPS_DAB

HowTo: Use Parameter Validation In PowerShell for ProjectWise (1 of 2)

In this post, I will be covering how to use Variable Validation Attributes within PowerShell. In a follow-up post, I will be expanding on this to add ProjectWise specific Variable Validation Attributes.

For many of us, we have developed a bunch of functions to accomplish some task(s). Within our functions we can have parameters which require some data or values to be passed into them. To ensure these parameters are receiving what we expect as proper values (data type, not null, etc.), we often add some code in our script to test or validate these values. If the value(s) don’t meet certain criteria, we exit the function.

So, in this post I am going to create a simple function to demonstrate how to use the Variable Validation Attributes within PowerShell. Hopefully, through this demonstration you will understand the benefits of using them.

FUNCTION Definition

First thing I need to do is create the initial function.  The following function demonstrates using code to validate parameter values. The function has three parameters which accept string values. We have a ProjectWise folder, a local folder and a local file. This function could be used to import the specified file into the provided ProjectWise folder.

In the BEGIN block of code, the first test determines if any of the parameter values contain a null or empty string. Then we will determine if the provided ProjectWise folder exists in the current ProjectWise datasource. Next, we will determine if the local folder and file are both valid. And finally, test to determine if the file provided is of the correct file type.

If any errors are encountered within the validation code, the Continue variable will be set to false which will cause the function to exit within the Process code block.

FUNCTION Test-Function {
    param (    
        # ProjectWise folder to import document in to.
        [Parameter( Mandatory = $true )]
        [string] $ProjectWiseFolder,

        # Local folder contain the file to be imported.
        [Parameter( Mandatory = $true )]
        [string] $LocalFolderPath,

        # File to be imported. Must be an Excel file.
        [Parameter( Mandatory = $true )]
        [string] $FileName
    ) # end param...

    BEGIN {
        $Continue = $true
        try {

            # Test is determine if any of the provided values are null or empty strings.
            if([string]::IsNullOrEmpty($ProjectWiseFolder) `
                -or [string]::IsNullOrEmpty($LocalFolderPath) `
                    -or [string]::IsNullOrEmpty($FileName)) {
                throw 'A null or empty string was passed.'
            }

            <# Test to determine if ProjectWise folder is a valid folder. 
                Requires that you be logged into a ProjectWise datasource. #>
            if( -not (Get-PWFolders -FolderPath $ProjectWiseFolder -JustOne)) {
                throw "ProjectWise folder '$ProjectWiseFolder' was not found."
            }

            # Test to determine if the provided local folder path is a valid folder.
            if( -not (Test-Path -Path $LocalFolderPath -PathType Container)) {
                throw "Folder '$LocalFolderPath' not found."
            }

            # Test to determine if provided file exists.
            if( -not ( Get-ChildItem -Path "$($LocalFolderPath)\$FileName" -File )) {
                throw "File '$($LocalFolderPath)\$FileName' not found." 
            }

            # Test to determine if provided file is the correct file type.
            if( -not ($FileName.EndsWith('.xlsx'))) {
                throw "File '$($LocalFolderPath)\$FileName' is the correct file type." 
            }

        } catch {
            Write-Warning -Message "[BEGIN] Error occurred. $($Error[0])"
            $Continue = $false
        }
    } # end BEGIN...

    PROCESS {
        try {
            if( -not ($Continue)) {
                throw 'Exiting function.'
            }

            Write-Host "[PROCESS] ProjectWise folder '$ProjectWiseFolder' was found." -ForegroundColor Green
            Write-Host "[PROCESS] Folder '$LocalFolderPath' was found." -ForegroundColor Green
            Write-Host "[PROCESS] File '$FileName' was found." -ForegroundColor Green

        } catch {
            Write-Warning -Message "[PROCESS] Error occurred. $($Error[0])"
        }
    } # end PROCESS...

    END { } # end END...
} # end FUNCTION Test-Function...

The following images demonstrate how the function will perform with valid and invalid parameter values included.

Invalid ProjectWise folder passed:

invalidPWFolder

Invalid local folder passed:

invalidLocalFolder

Invalid file passed:

invalidfile

Invalid file type passed:

invalidFileType

Success parameter values provided:

successful

Although, using code to validate parameter values works fine, it does require that we actually enter the function to accomplish the tests within the BEGIN block of code. If the provided variables are invalid, a warning is presented and we exit the function.

To simply this, we could implement one or more of the available Variable Validation Attributes provided with PowerShell.

Variable Validation Attributes

The following is from the PowerShell help.

Validation attributes direct PowerShell to test the parameter values that
users submit when they call the advanced function. If the parameter values
fail the test, an error is generated and the function isn’t called. You can
also use some of the validation attributes to restrict the values that
users can specify for variables.

Get-Help about_Functions_Advanced_Parameters

Below are a few of the PowerShell Variable Validation Attributes available which I use regularly:

  • [ValidateNotNullOrEmpty()]
  • [ValidatePattern()]
  • [ValidateScript()]
  • [ValidateSet()] – Not demonstrating this, however it is very useful.

Updated FUNCTION Definition

Now, we will update the Test-Function function to add the Variable Validation Attributes to improve its performance and functionality. You will notice the simplification of the code within the function. We eliminated all of the code within the BEGIN block of code and removed the need to test the Continue variable. This is a much cleaner approach.

One change I had to make for demonstration purposes is that the FileName parameter was renamed to FilePathName and now includes the full path and name of the file on the local machine.  The other thing to note is how the parameter value is passed to the validation attribute test.  We utilize the $_ which indicates the current value on the pipeline. Again, be sure to read the help information available.

FUNCTION Test-Function2 {
    param ( 
        # ProjectWise folder to import document in to.
        [ValidateNotNullOrEmpty()]
        [ValidateScript({ Get-PWFolders -FolderPath $_ -JustOne })]        
        [Parameter( Mandatory = $true )]
        [string] $ProjectWiseFolder,

        # Local folder contain the file to be imported.
        [ValidateNotNullOrEmpty()]
        [ValidateScript({ Test-Path -Path $_ -PathType Container})]       
        [Parameter( Mandatory = $true )]
        [string] $LocalFolderPath,

        # File to be imported. Must be an Excel file.
        [ValidateNotNullOrEmpty()]
        [ValidateScript({ Get-ChildItem -Path $_ -File })]
        [ValidatePattern( '.xlsx' )]
        [Parameter( Mandatory = $true )]
        [string] $FilePathName
    ) # end param...

BEGIN { } # end BEGIN...

PROCESS {
    try {

        Write-Host "[PROCESS] ProjectWise folder '$ProjectWiseFolder' was found." -ForegroundColor Green
        Write-Host "[PROCESS] Folder '$LocalFolderPath' was found." -ForegroundColor Green
        Write-Host "[PROCESS] File '$FilePathName' was found." -ForegroundColor Green

    } catch {
        Write-Warning -Message "[PROCESS] Error occurred. $($Error[0])"
    }
} # end PROCESS...

END { } # end END...
} # end FUNCTION Test-Function...

Again, notice the simplification of the code. Now, we will never get into the function if any of the parameter values are invalid.  This eliminates the need to add a bunch of error handling code within the function itself.  Seems to me to be a much better approach.

The following images demonstrate the new functionality or behavior. It is very important to read the error messages being returned. The reason for the error should be clearly stated.

Invalid ProjectWise folder passed:

function2projectwisefoldererror

Invalid folder passed:

function2foldererror

Invalid file passed:

function2fileerror

Invalid file type passed:

function2 patternerror

Success parameter values provided:

function2success

Summary

So lets recap what we have done. We have created a function which contained a lot of parameter value validation within the BEGIN block of code.  This validation code ensured that the function only uses good data. Then, we demonstrated what to expect when using this function, both successes and failures. We then updated this function to replace the validation code within the BEGIN block with the Variable Validation Attributes within the parameter definitions. This ultimately accomplishes the same validation of parameter values, however it is accomplished prior to ever entering the function and simplifies our code.


Experiment with it and have fun.

Hopefully, you find this useful. Please let me know if you have any questions or comments.  If you like this post, please click the Like button at the bottom of the page.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.