PowerShell How-To
Understanding PowerShell Scriptblocks
Scriptblocks are a ubiquitous part of PowerShell and are a construct that every PowerShell developer should understand.
- By Adam Bertram
- 05/08/2019
The scriptblock is a unique type of construct in PowerShell that allows developers to "compartmentalize" executable code and use it in various places. Lots of programming languages have a concept of an anonymous function or a lambda. A function is just some code that's packaged to be executed at once. A scriptblock is a function, but it's anonymous. A scriptblock is an expression. You can think of it just like a function but without a name. A scriptblock contains code just like a function does, but is called differently and -- more importantly -- is portable.
A scriptblock can be assigned to a variable, unlike a function. A function can return something that can be assigned to a variable, but a function can't be the variable; a scriptblock can.
Creating Scriptblocks
For example, perhaps I've got a function called New-Thing. That function calls Write-Host to display something on the screen.
function New-Thing {
param()
Write-Host "Hi! I am in New-Thing"
}
New-Thing
I can copy and paste this function along with the call into my console and see that it returns the text, "Hi! I am in New-Thing!" to the console, as we'd expect. We had to run New-Thing for the function to run. Let's now replicate this with a scriptblock by first assigning it to a variable.
PS> $newThing = { Write-Host "Hi! I am in a scriptblock!" }
Executing Scriptblocks
All scriptblocks are built with curly braces and by placing the code to execute inside. I now have a $newThing variable. You might expect that I could just read the contents of $newThing and would get the same output, right? Nope. You can see that when looking at a scriptblock like this, PowerShell takes the entire code literally. It doesn't realize that Write-Host is a command to execute and the "Hi! I am in a scriptblock!" is a parameter to that function.
PS> $newThing = { Write-Host "Hi! I am in a scriptblock!" }
PS> $newThing
Write-Host "Hi! I am in a scriptblock!"
PowerShell is showing you the value of the scriptblock. It's not executing the code inside. To tell PowerShell to run the code inside, you'll have to use the ampersand.
PS> & $newThing
Hi! I am in a scriptblock!
The ampersand tells PowerShell to execute the scriptblock expression. In essence, it's telling PowerShell that the stuff between the curly braces is code and to run it as code.
Passing Arguments to Scriptblocks
Like functions, you can pass "parameters" to scriptblocks also known as arguments. This allows developers to pass in real-time values to scriptblocks when they execute. To pass arguments to scriptblocks, we can make this happen a couple of different ways. We can either create a param() block or use the built-in $args variable.
For example, perhaps we'd like to pass in a first and last name to a scriptblock as part of some larger script. We have a scriptblock that looks like this:
$userMsg = { Write-Host "Processing user $user..." }
When running this scriptblock on our local computer (not getting into remote scriptblocks), we can define the $user variable in the same session, and when we execute the scriptblock, it will expand as expected.
PS> $userMsg = { Write-Host "Processing user $user..." }
PS> $user = 'Adam Bertram'
PS> & $userMsg
Processing user Adam Bertram...
However, there are times out of the scope of this article where this will not work. We can also define param() blocks inside of the scriptblock just like a function and pass in a value by position, as shown below:
PS> $userMsg = { param($scriptblockuser) Write-Host "Processing user $scriptblockuser..." }
PS> & $userMsg 'Adam Bertram'
Processing user Adam Bertram...
Finally, we can use the built-in $args variable, which is an array of each argument that's passed to the scriptblock. You can see below that we get the same result:
PS> $userMsg = { Write-Host "Processing user $($args[0])..." }
PS> & $userMsg 'Adam Bertram'
Processing user Adam Bertram...
Scriptblocks are a ubiquitous part of PowerShell and are a construct every PowerShell developer should understand. Scriptblocks can not only be used in local sessions like we've done here, but can also be used to pass code to remote computers using commands like [Invoke-Command] -- but we'll save that for another article.
About the Author
Adam Bertram is a 20-year veteran of IT. He's an automation engineer, blogger, consultant, freelance writer, Pluralsight course author and content marketing advisor to multiple technology companies. Adam also founded the popular TechSnips e-learning platform. He mainly focuses on DevOps, system management and automation technologies, as well as various cloud platforms mostly in the Microsoft space. He is a Microsoft Cloud and Datacenter Management MVP who absorbs knowledge from the IT field and explains it in an easy-to-understand fashion. Catch up on Adam's articles at adamtheautomator.com, connect on LinkedIn or follow him on Twitter at @adbertram or the TechSnips Twitter account @techsnips_io.