Behind the PowerShell Pipeline logo

Behind the PowerShell Pipeline

Subscribe
Archives
May 16, 2025

More PowerShell Parameter Validations

Let's continue our exploration of lesser known PowerShell parameter and validation attributes. I trust most of you are familiar with [ValidateSet()], [ValidateRange()], and [ValidatePattern()]. I always to try to use parameter validation to ensure parameter values are correct and increase the likelihood of successful execution.

However, before we jump into the main topic, I have another parameter attribute that I want to make sure you know about. This attribute will be especially useful with your commands that utilize custom objects.

PSTypeName Attribute

Here's a demonstration function that creates a custom object and writes it to the pipeline.

Function Get-TestSample {
    [CmdletBinding()]
    [OutputType('psTestSample')]
    Param([string]$Name = $env:USERNAME)

    [PSCustomObject]@{
        PSTypeName   = 'psTestSample'
        Name         = $Name
        ProcessCount = (Get-Process).Count
        Comment      = 'This is a test sample'
        PSVersion    = $PSVersionTable.PSVersion
    }
}

Using it is simple enough.

PS C:\> Get-TestSample | Tee -Variable s

Name ProcessCount Comment               PSVersion
---- ------------ -------               ---------
Jeff          369 This is a test sample 7.5.1

And I can verify the type name of the object.

PS C:\> $s | Get-Member

   TypeName: psTestSample

Name         MemberType   Definition
----         ----------   ----------
Equals       Method       bool Equals(System.Object obj)
GetHashCode  Method       int GetHashCode()
GetType      Method       type GetType()
ToString     Method       string ToString()
Comment      NoteProperty string Comment=This is a test sample
Name         NoteProperty string Name=Jeff
ProcessCount NoteProperty int ProcessCount=369
PSVersion    NoteProperty semver PSVersion=7.5.1

This function might be part of a module with a corresponding Set command. Following the PowerShell module you would expect to pipe the output of Get-TestSample to Set-TestSample.

Function Set-TestSample {
    [cmdletbinding()]
    [OutputType('psTestSample')]
    Param(
        [Parameter(Position = 0, Mandatory,ValueFromPipeline)]
        [psTestSample]$TestSample,
        [string]$Name,
        [string]$Comment
    )
    Process {
        if ($Name) {
            $TestSample.Name = $Name
        }
        If ($Comment) {
            $TestSample.Comment = $Comment
        }
        $TestSample.ProcessCount = (Get-Process).Count
        $TestSample.PSVersion    = $PSVersionTable.PSVersion
        $TestSample
    }
}

You want to ensure that the object is a psTestSample object so that your code will run. But there is a problem with this command.

PS C:\> Help Set-TestSample
Get-Help:
Line |
  64 |      $help = Get-Help @PSBoundParameters
     |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Unable to find type [psTestSample].
PS C:\> $s | Set-TestSample -name Foo -Comment "Updated"
InvalidOperation:
Line |
   6 |          [psTestSample]$TestSample,
     |          ~~~~~~~~~~~~~~
     | Unable to find type [psTestSample].

PowerShell doesn't know anything about your custom type. You could write your own validation code in the function, but that's a lot of work. Instead, you can use the PSTypeName attribute to tell PowerShell about your custom type.

Function Set-TestSample {
    [cmdletbinding()]
    [OutputType('psTestSample')]
    Param(
        [Parameter(Position = 0, Mandatory,ValueFromPipeline)]
        [PSTypeNameAttribute('psTestSample')]
        [PSObject]$TestSample,
        [string]$Name,
        [string]$Comment
    )
    Process {
        if ($Name) {
            $TestSample.Name = $Name
        }
        If ($Comment) {
            $TestSample.Comment = $Comment
        }
        $TestSample.ProcessCount = (Get-Process).Count
        $TestSample.PSVersion    = $PSVersionTable.PSVersion
        $TestSample
    }
}

Set the parameter type to PSObject and add the PSTypeNameAttribute attribute. Now PowerShell knows about your custom type.

Want to read the full issue?
GitHub Bluesky LinkedIn Mastodon https://jdhitsoluti…
Powered by Buttondown, the easiest way to start and grow your newsletter.