Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Mastering PowerShell Scripting

You're reading from   Mastering PowerShell Scripting Automate repetitive tasks and simplify complex administrative tasks using PowerShell

Arrow left icon
Product type Paperback
Published in May 2024
Publisher Packt
ISBN-13 9781805120278
Length 826 pages
Edition 5th Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
Chris Dent Chris Dent
Author Profile Icon Chris Dent
Chris Dent
Arrow right icon
View More author details
Toc

Table of Contents (23) Chapters Close

Preface 1. Introduction to PowerShell 2. Modules FREE CHAPTER 3. Variables, Arrays, and Hashtables 4. Working with Objects in PowerShell 5. Operators 6. Conditional Statements and Loops 7. Working with .NET 8. Files, Folders, and the Registry 9. Windows Management Instrumentation 10. Working with HTML, XML, and JSON 11. Web Requests and Web Services 12. Remoting and Remote Management 13. Asynchronous Processing 14. Graphical User Interfaces 15. Scripts, Functions, and Script Blocks 16. Parameters, Validation, and Dynamic Parameters 17. Classes and Enumerations 18. Testing 19. Error Handling 20. Debugging 21. Other Books You May Enjoy
22. Index

Introduction to splatting

Splatting is a way of defining the parameters of a command before calling it. This is an important and often underrated technique that the PowerShell team added to PowerShell 2.

Splatting is often used to solve three potential problems in a script:

  • Long lines caused by commands that need many parameters
  • Conditional use of parameters
  • Repetition of parameters across several commands

Individual parameters are written in a hashtable (@{}), and then the @ symbol is used to tell PowerShell that the content of the hashtable should be read as parameters.

This example supplies the Name parameter for the Get-Process command, and is normally written as Get-Process -Name explorer:

$getProcess = @{
    Name = 'explorer'
}
Get-Process @getProcess

In this example, getProcess is used as the name of the variable for the hashtable. The name is arbitrary; any variable name can be used.

Splatting can be used with cmdlets, functions, and scripts. Splatting can be used when the call operator is present, for example:

$getProcess = @{
    Name = 'explorer'
}
& 'Get-Process' @getProcess

The ability to use splatting with the call operator is useful if the command name itself is held in a variable.

The uses of splatting are explored in the following sections.

Splatting to avoid long lines

The benefit of splatting is most obvious when working with commands that expect a larger number of parameters.

This first example uses the module ScheduledTasks to create a basic task that runs once a day at midnight:

$taskAction = New-ScheduledTaskAction -Execute pwsh.exe -Argument 'Write-Host "hello world"'
$taskTrigger = New-ScheduledTaskTrigger -Daily -At '00:00:00'
Register-ScheduledTask -TaskName 'TaskName' -Action $taskAction -Trigger $taskTrigger -RunLevel 'Limited' -Description 'This line is too long to read'

Each of the commands is spread out over multiple lines; it is hard to see where one ends and the next begins.

Commands can also be spread out using a backtick, the escape character in PowerShell, as shown here:

$taskAction = New-ScheduledTaskAction `
    -Execute pwsh.exe `
    -Argument 'Write-Host "hello world"'
$taskTrigger = New-ScheduledTaskTrigger `
    -Daily `
    -At '00:00:00'
Register-ScheduledTask `
    -TaskName 'TaskName' `
    -Action $taskAction `
    -Trigger $taskTrigger `
    -RunLevel 'Limited' `
    -Description 'This line is too long to read'

This approach is relatively common, but it is fragile. It is easy to miss a backtick from the end-of-line, or to accidentally add a space after a backtick character. Both break continuation and the command executes but with an incomplete set of parameters; afterward, an error may be displayed, or a prompt may be shown, depending on the parameter (or parameters) it missed.

This problem is shown in the following screenshot, where a space character has been accidentally included after a backtick following the Daily switch parameter:

Figure 1.6: Space after the escape character

Splatting provides a neater, generally easier-to-read, and more robust alternative. The following example shows one possible way to tackle these commands when using splatting:

$newTaskAction = @{
    Execute = 'pwsh.exe'
    Argument = 'Write-Host "hello world"'
}
$newTaskTrigger = @{
    Daily = $true
    At    = '00:00:00'
}
$registerTask = @{
    TaskName    = 'TaskName'
    Action      = New-ScheduledTaskAction @newTaskAction
    Trigger     = New-ScheduledTaskTrigger @newTaskTrigger
    RunLevel    = 'Limited'
    Description = 'Splatting is easy to read'
}
Register-ScheduledTask @registerTask

Switch parameters may be treated as if they are Boolean when splatting.

The Daily parameter that was defined in the previous example is a switch parameter.

The same approach applies to Confirm, Force, WhatIf, Verbose, and so on.

Conditional use of parameters

Conditional use of parameters is one of the most important ways in which splatting can help.

If a command must be run and the parameters for a command can change based on user input or other circumstances, then it may be tempting to repeat the entire command. For example, a Credential parameter might be conditionally used.

The command may be repeated entirely based on there being a value for the Credential variable:

if ($Credential) {
    Get-ADUser 'Enabled -eq $true' -Credential $Credential
} else {
    Get-ADUser 'Enabled -eq $true'
}

The disadvantage of this approach is that any change to the command must be repeated in the second version.

Alternatively, a splatting variable may be used, and the Credential parameter added only when it is needed:

$params = @{}
if ($Credential) {
    $params['Credential'] = $Credential
}
Get-ADUser 'Enabled -eq $true' @params

Using splatting in this manner ensures only one version of the command must be maintained, reducing the risk of introducing a bug when making changes.

Splatting to avoid repetition

Splatting may be used to avoid repetition when a parameter must be optionally passed on to several different commands. It is possible to splat more than one set of parameters.

In this example, the ComputerName and Credential parameters are used by two different commands:

# Parameters used to authenticate remote connections
$remoteParams = @{
    Credential   = Get-Credential
    ComputerName = $env:COMPUTERNAME
}
# Parameters which are specific to Test-WSMan
$testWSMan = @{
    Authentication = 'Default'
    ErrorAction    = 'SilentlyContinue'
}
# By default, do not pass any extra parameters to New-CimSession
$newCimSession = @{}
if (-not (Test-WSMan @testWSMan @remoteParams)) {
    # If WSMan fails, use DCOM (RPC over TCP) to connect
    $newCimSession['SessionOption'] = New-CimSessionOption -Protocol Dcom
}
# Parameters to pass to Get-CimInstance
$getCimInstance = @{
    ClassName  = 'Win32_Service'
    CimSession = New-CimSession @newCimSession @remoteParams
}
Get-CimInstance @getCimInstance

This example takes advantage of several features:

  • It is possible to splat no parameters using an empty hashtable (@{}) when all the parameters are conditionally added.
  • It is possible to test conditions and dynamically add parameters at runtime (if needed).
  • It is possible to splat more than one set of parameters into a command.

As the preceding example shows, it is possible to dynamically choose the parameters that are passed to a command without having to write the command in full more than once in a script.

Splatting and positional parameters

It is possible, although rare and inadvisable in production scripts, to splat positional parameters; that is, to splat a parameter without stating a parameter name.

This can be seen with the Rename-Item command, which has two positional parameters: Path and NewName. Rename-Item may be run as follows:

Rename-Item oldname.txt newname.txt

An array to splat these positional parameters looks as follows:

$renameItem = 'oldname.txt', 'newname.txt'
Rename-Item @renameItem

A splatting variable with positional parameters may be used with executable files (.exe files), although it is often difficult to see any difference between splatting and using a normal variable. For example, both of the following commands execute in the same way:

$argumentList = '/t', 2
timeout.exe $argumentList
timeout.exe @argumentList

Splatting is a powerful technique and can be used to make code more readable by reducing the line length or repetition.

When using splatting, string values in the hashtable must be quoted. Conversely, when using a parameter directly, it is often unnecessary. The parser is responsible for deciding how statements and expressions should be interpreted.

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime