Microcode: PowerShell Scripting Trick: Fun With Parameter Binding: The Fake Parameter Set Trick

I’ve been hearing a lot of questions recently about what things you can do with advanced functions.  People seem to be aching for good examples of using PowerShell V2 functions, and, since I’ve discovered a few handy tricks for advanced functions, I thought I’d start to share them there in a series called “Fun with Parameter Binding.”

Here’s volume one: The Fake Parameter Set Trick

I found myself wanting to make an advanced function that took something strongly typed (in this case, the CommandInfo object, which is the base object for what you see when you run Get-Command) from the pipeline and returned items that matched a certain characteristic.  If I didn’t pipeline in any items, I wanted to get all of the commands and check for the same characteristic.

What I really wanted was the function to act two ways, one parameterized, one unparameterized (like how you can run Get-Process or Get-Process PowerShell*)

I know of one way to approach this, using the $psBoundParameters variable (see this enlightening post by Marcel Ortiz Soto), but I recently happened upon another approach that I find kind of novel.  I call it the fake parameter set trick.

Here’s an example:

 [CmdletBinding(DefaultParameterSetName="All")]            
                
    param(            
    [Parameter(Mandatory=$true,            
        ParameterSetName="Command",            
        ValueFromPipeline=$true)]            
    [Management.Automation.CommandInfo]            
    $command            
    )            
                
    process {            
        $psCmdlet.ParameterSetName               
    }

The CmdletBinding attribute at the top of the function is one of the markers that the function is an advanced function, and it specifies the DefaultParameterSetName.  If no default parameter set name is specified, it would go ahead and default to whichever ParameterSetName it found on a parameter.  If you didn’t every mention a ParameterSetName, then the parameter set name would implicitly be __AllParameterSets.

In my case, I’ve set the DefaultParameterSetName to All.  But there aren’t any parameters at all in All.  In fact, for All intents and purposes, All is nothing.  All is a fake parameter set.

This lets me mark the $command parameter as mandatory and from pipeline, and lets me easily figure out if the parameter is there or not.  This is ideal for building good Get- advanced functions, because Get- cmdlets and functions tend to either be able to retrieve all of the data or retrieve a filtered subset of the data.

Hope this Helps,

James Brundage