Sunday, August 19, 2012

Splat in the Hat

In PowerShell the @ character is called the splat operator.  I'm still trying to figure out why it is called splat.
I'm pretty sure that's not why.  Nevertheless the splat operator has many uses in PowerShell.

In a previous post I demonstrated using the splat operator to create a custom object.

$X = New-Object PSObject -Properties @{
     Name="ObjectName";
     SomeValue=1;
     AnotherValue=10
}

The splat operator is also used to define an array.

$Array = @("one","two","three","four")

PowerShell is forgiving and will let you define an array without the splat operator.

$Array = "one","two","three","four"

But if you need to force the results to be an array you can use the splat operator.  I frequently do this if I'm creating an array of custom objects.  I first define an empty array, then fill it with the objects.

$Procs = @()
foreach ($P in (get-process | get-unique)) {
   $New = New-Object PSObject -Property @{
      Name=$P.ProcessName;
      Company=$P.Company;
      Product=$P.Product;
      Version=$P.ProductVersion
   }
   $Procs += $New
}
$Procs



The splat operator can also be used to force the results of a command into an array.  Enclose the command or cmdlet in parentheses and precede the opening parenthesis with the splat operator.
In the above example the variable $X has a length of 843 because it measures the length of the string returned by the Dir command.  $Y and $Z have a length of 1 because it is the length of the array.  The length of the first and only element of those single element arrays matches the length of the string $X.  I included the variable $Z to show another way of forcing a variable to be an array.

The splat operator is also used to create hash tables.  Hash tables are similar to dictionary objects in VBScript but are much more versatile.  A basic hash table lets you add and remove members in addition to doing searches.  To create the hash table start with the splat, enclose the table in curly braces, and separate items with semi-colons.

$Meals = @{"Breakfast"="Eggs";"Lunch"="Sandwich";"Supper"="Chicken"}


Another use for hash tables (and by association our friend the splat operator) is to define a group of parameters for cmdlets.  In this use the keys are the named parameters and the values are the input for the parameters.

Notice that when the hash table is used to provide parameters to the cmdlet the variable name is preceded with the splat operator instead of the dollar sign.  This tells PowerShell to process the variable as a hash table and use the keys and values as parameters to the cmdlet.

This technique is really useful for making code more readable.  The cmdlet Write-EventLog lets you add records to the Windows event logs.  In the example below I use the source WSH because its events have free form messages which allows me to use Get-WinEvent to confirm the results.

Write-EventLog -LogName Application -Source WSH -EventID 0 -EntryType Information -Message "I added this to the event log from PowerShell"


That works but the Write-EventLog cmdlet gets cumbersome with all of the parameters on a single line.  If I splat the parameters in a hash table the code becomes much easier to read and costs very little extra typing.

$ELParams = @{
    'LogName' = 'Application';
    'Source'  = 'WSH';
    'EventId' = 0;
    'EntryType'= 'Information';
    'Message' = 'I splatted this to the Application log using PowerShell'
}
Write-EventLog @ELParams


Note that while I hard coded all of the parameter names and values in the hash table I could just as easily use variables for any of them.  This allows for some sophisticated processing inside loops and user defined functions.

One final use for the splat operator is the Here-String.  A Here-String is PowerShell's facility for specifying a large block of text that spans multiple lines.  Start the bock of text with the splat and quote @" and end the block with a quote and splat "@.  (On a personal note "Quote and Splat" is the law firm who handled my divorce settlement.)  Inside the Here-String you can specify line breaks and include quotes and other special characters.  The Here-String will display just as you specified.


The splat operator gives us a variety of shortcuts to keep our code efficient and tidy.  But remember that with great power comes great responsibility.  So remember to splat wisely, unlike this juvenile.

Commentors:  Seriously, does anybody know why they call it splat?