To Splat or Not to Splat, That’s the Question

Splatting Helps the Readability of PowerShell Code

Splatting is a way to define and use values for parameters dent to PowerShell cmdlets and functions. Instead of specifying a value for each parameter when running a cmdlet, you create a hash table and add the parameters and their values to the hash table. Then you specify the hash table when running the cmdlet. The idea is to avoid long command lines that might or might not be broken up with backticks. Long command lines can sometimes be difficult to scan to understand exactly what the intent of a command is.

Those who endorse splatting say that it’s easy to forget a parameter or a backtick when composing long command lines. In addition, the parameters and values passed in long command lines can be harder to read than a nicely formatted hash table.

Using a development tool like Visual Studio Code will help to make sure that commands are properly formed. After that, using splatting to pass parameters is down to personal choice. And if you pay for a GitHub Copilot license, you’ll discover that Copilot does an excellent job of filling parameter values.

Example of Splatting

Here’s an example of how splatting works. The Set-User command updates many properties of a user account. Note the use of backticks to break the command over several lines:

Set-User -Identity Ben.James -Office 'Dublin Center' -City 'Dublin' `
-CountryOrRegion 'Ireland' -Department 'Sales and Marketing' `
 -DisplayName 'Ben James (Sales)' -Initials 'BJ' -Title 'Senior Lead Manager' ` 
-StateOrProvince 'Leinster' -StreetAddress '1, Liffey Walk' -PostalCode 'D01YYX1' `
-Confirm:$False

Splatting allows you to do this instead:

$Parameters = @{}
$Parameters.Add("Office", "Galway")
$Parameters.Add("Department", "Business Development")
$Parameters.Add("DisplayName", "Ben James (BusDev)")
$Parameters.Add("StateOrProvince", "Connacht")
$Parameters.Add("PostalCode", "GY1H1842")
$Parameters.Add("StreetAddress", "Kennedy Center")
$Parameters.Add("City", "Galway")
$Parameters.Add('Title', "Senior Development Manager")
$Parameters.Add("Identity", "Ben.James@office365itpros.com")
$Parameters.Add("Confirm", $false)

Set-User @Parameters

Adding or changing a parameter is a matter of updating the hash table.

An advantage of using splatting is that it is easy to update objects with common parameters. For instance, to update another user who shares the same office and location values, we can do this:

Set-User -Identity Jane.Sixsmith@office365itpros.com -DisplayName 'Jane Sixsmith' 
-Title 'Promotions Manager' @parameters

PowerShell applies the values for the parameters in the hash table except where a parameter value is explicitly passed.

Microsoft Graph PowerShell SDK Cmdlets And Splatting

In script examples used by articles on this site, we spell out parameters because of personal preference. In addition, the cmdlets in the Microsoft Graph PowerShell SDK can use a construct like splatting when updating or creating objects, meaning that splatting is less of an issue. Because the SDK cmdlets are based on Graph APIs, cmdlets that implement POST and PATCH requests require commands to pass a request body in the Body parameter.

Here’s an example of using the Update-MgUser cmdlet to update a set of properties for a user account with a request body created as a hash table:

$UserId = (Get-MgUser -UserId 'Michelle.duBois@office365itpros.com').id
$Body = @{}
$Body.Add("Office", "Galway")
$Body.Add("Department", "Business Development")
$Body.Add("DisplayName", "Ben James (BusDev)")
$Body.Add("State", "Connacht")
$Body.Add("PostalCode", "GY1H1842")
$Body.Add("StreetAddress", "Kennedy Center")
$Body.Add("City", "Galway")
$Body.Add('JobTitle', "Senior Development Manager")

Update-MgUser -UserId $UserId -BodyParameter $Body

The same hash table can be used with splatting:

Update-MgUser -UserId $UserId @Body

Even complex Graph SDK commands can be converted to splatting. Take the example of using the Get-MgUser cmdlet shown in Figure 1. This is an advanced Graph query because it’s checking the service plans held in (a multivalued property) assigned to user accounts to find accounts with a specific plan. As written, the command is spread over three lines using backticks.

A complex Get-MgUser command.

Splatting
Figure 1: A complex Get-MgUser command

Graph SDK cmdlets like Get-MgUser are based on GET Graph queries so there’s no need to pass a request body. However, the cmdlet parameters can be put into a hash table and passed to cmdlets. Here’s an example using an advanced query with Get-MgUser:

[guid]$SPOPlanId = "5dbe027f-2339-4123-9542-606e4d348a72"
$Body = @{}
$Body.Add("Filter", "assignedPlans/any(s:s/serviceplanid eq $SPOPlanId and capabilityStatus eq 'Enabled')")
$Body.Add("ConsistencyLevel", "eventual")
$Body.Add("Countvariable", "Test")
$Body.Add("Pagesize", "999")
$Body.Add("Property", "Id, displayName, userprincipalName, assignedLicenses, assignedPlans, department, country")
$Body.Add("Sort", "DisplayName")
$Body.Add("All", $true)

[array]$Users = Get-MgUser @Body

Note that switch parameters (like -All in this example) that don’t take a value when run in a command need $true as the value for their entry in the hash table.

Splatting is A Personal Choice

One of the nice things about PowerShell is the variety of styles supported for writing code. Some favor dense masses of commands including some pretty hard-to-understand pipelined code. Some eschew functions and others like to lay out commands with plenty of white space in between. Splatting does a job of defining and passing parameters. It’s up to you to decide how to use it.


Learn how to exploit the data and tools available to Microsoft 365 tenant administrators through the Office 365 for IT Pros eBook. We love figuring out how things work.

4 Replies to “To Splat or Not to Splat, That’s the Question”

  1. Instead of creating an empty hashtable object and adding elements one at a time, you can create just a hashtable:

    $Body = @{
    Office = “Galway”
    Department = “Business Development”
    }

    Update-MgUser -UserId $UserId @Body

    1. I know. But I like constructing hash tables in this manner. It just seems more logical and easier to do when building hash tables programmatically.

  2. Another great article, Tony! I’m a huge fan of splatting and generally avoid using backticks except in rare cases. I tend to start typing commands the “traditional” way with parameters all on the same line to leverage tab completion/IntelliSense. I then let VS Code convert those that have become unwieldy to use splatting, as described here:

    https://mikefrobbins.com/2023/10/19/automatically-convert-a-powershell-command-to-use-splatting/

    One thing I’ve noticed is that the following doesn’t seem to be true for me in PowerShell version 5.1:

    “PowerShell applies the values for the parameters in the hash table except where a parameter value is explicitly passed.”

    If I run this (somewhat silly) example:

    $getMgUserSplat = @{
    UserId = ‘user1@company.com’
    Property = ‘Id’, ‘UserPrincipalName’, ‘mySite’
    }
    $user1 = Get-MgUser @getMgUserSplat
    $user2 = Get-MgUser @getMgUserSplat -UserId ‘user2@company.com’

    I get the following error on that second Get-MgUser:

    Get-MgUser : Cannot bind parameter because parameter ‘UserId’ is specified more than once. To provide multiple values to parameters that can accept multiple values, use the array syntax. For example, “-parameter value1,value2,value3”.

    When this comes up, I just replace the value in the hash table before running the second instance of the command:

    $user1 = Get-MgUser @getMgUserSplat
    $getMgUserSplat.UserId = ‘user2@company.com’
    $user2 = Get-MgUser @getMgUserSplat

    or, limit the hash table to only the “static” parameters and pass the variable parameters explicitly:

    $getMgUserSplat = @{
    Property = ‘Id’, ‘UserPrincipalName’, ‘mySite’
    }
    $user1 = Get-MgUser @getMgUserSplat -UserId ‘user1@company.com’
    $user2 = Get-MgUser @getMgUserSplat -UserId ‘user2@company.com’

    1. It might just be that UserId is a mandatory parameter… Does the same error occur for other parameters?

      I did this:

      $Params = @{}
      $Params.Add(“JobTitle”, “Road Sweeper”)
      $Params.Add(“OfficeLocation”, “Paris”)
      Update-MgUser -UserId Rene.Artois@Office365itpros.com -Office “Nouvon” -JobTitle “Chief” @Params

      Get-MgUser -userid Rene.Artois@Office365itpros.com -Property Id, OfficeLocation, JobTitle | Select OfficeLocation, JobTitle

      OfficeLocation JobTitle
      ————– ——–
      Nouvon Chief

      As you can see, the explicit parameters took precedence over those in the hash table. But this is PowerShell 7.4.2.

      Who knows what might happen elsewhere…

Leave a Reply

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