PowerShell Quick Script: Invoke-Splat

One of the features added to PowerShell v2 (and of course continued with PowerShell v3) is splatting. Without going into extreme detail (there are plenty of other blogs and books that do that), splatting allows you to pass parameters to a PowerShell cmdlet via an associative array (that is a fancy name for a hash table).

The hash table contains the parameter name as a key and the parameter's value as a value. The hash table contains two matched arrays, the keys array and the values array. For example, if a hash table contains three values, then accessing $hash.keys[ 1 ] will provide the name of a given hash entry and $hash.values[ 1 ] will provide the corresponding value for that entry.

The big deal behind splatting is that it allows you to easily construct custom parameter lists that get passed to cmdlets based on the special needs of a calling script. That sounds dense. :) But it is a good thing. For example, if you want to call a cmdlet with different parameters based on the time of day, or on a particular computer, or whether your script was started with a switch parameter, or whether a particular string parameter has a value - then splatting is for you.

Splatting has a somewhat hidden advantage. Switch parameters require special handling under normal circumstances. With splatting, no special handling is required. You set a switch to $true or $false, without using special spacing and/or a colon.

I use splatting extensively in scripts I have developed since PowerShell v2 was released. Today, my friend Carl Webster, the Accidental Citrix Admin, asked about a way to simplify calling cmdlets in certain of his scripts. My answer was "use splatting". After a couple of back-and-forth emails, about the best way to use splatting, I concluded that the easiest thing to do was to generalize a routine to provide splatting for a cmdlet and pass that over to Carl.

After further thought and evolution on the basic concept of the routine I sent to Carl, I decided it could be a great deal more powerful (get it - powerful vs. PowerShell? HAHAHAHA) if I added in some logging capabilities and provided for the suppression of empty parameters. Thus was born Invoke-Splat. I have already taken Invoke-Splat and used it to simplify several of my own scripts.

Invoke-Splat takes the cmdlet to invoke as a parameter, plus all of the parameters for that cmdlet, as "parameter value" pairs, plus a couple of optional switch parameters to control Invoke-Splat itself. Invoke-Splat is dependent on PowerShell's named parameter matching, combined with positional parameter matching, and that everything that does not meet either of those, is stored in the special argument $args.

The splatNotEmpty switch ensures that parameters whose values evaluate as either null or empty strings are not passed as parameters to the called cmdlet. This is especially important for parameters that cannot normally be null or empty!

The splatDebug switch causes the cmdlet and each of the "parameter value" pairs to be output to the calling host.

The splatCmdlet string parameter is (obviously) the name of the cmdlet that will be executed with the other parameters.

Note that the other parameters may be empty!

For example:

Invoke-Splat Get-Process ID $PID FileVersionInfo $false -splatDebug

and

Invoke-Splat Get-Process ID $PID Name '' -splatDebug -splatNotEmpty

Without further ado, here is Invoke-Splat.

function Invoke-Splat
{
	Param(
		[string]$splatCmdlet,
		[switch]$splatNotEmpty,
		[switch]$splatDebug
	)

	## $args[ 0 .. n ] are matching "parameter argument" pairs

	$splats = @{}
	for( $i = 0; $i –lt $args.Length; $i = $i + 2 )
	{
		if( $splatNotEmpty )
		{
			## don’t pass arguments with empty strings
			if( ( $args[ $i + 1 ] –as [string] ).Length –gt 0 )  
			{
				$splats.$( $args[ $i ] ) = $args[ $i + 1 ]
			}
		}
		else
		{
			$splats.$( $args[ $i ] ) = $args[ $i + 1 ]
		}
	}
	if( $splatDebug )
	{
		write-host -ForeGroundColor Yellow "DEBUG: Invoke-Splat: cmdlet = $splatCmdlet"
		foreach( $entry in $splats.Keys )
		{
			write-host -ForeGroundColor Yellow "DEBUG: Invoke-Splat: entry: $entry = $($splats.$entry)"
		}
	}

	& $splatCmdlet @splats
}

Please follow me on Twitter: @essentialexch.

Thanks for your visit!

Published Friday, March 08, 2013 7:33 PM by michael
Filed under: ,

Comments

No Comments