understanding-powershell-scriptblocks

Understanding PowerShell Scriptblocks

Understanding PowerShell Scriptblocks

If you're not already familiar with scriptblocks, after reading this article, you'll begin to see them all over the place in PowerShell in the form of an opening and a closing curly brace.

Scriptblocks are an important and unique construct in PowerShell. Scriptblocks are essentially a portable unit of code that can be passed around and executed at will. 

A PowerShell scriptblock is an expression. An expression is a piece of code PowerShell knows how to execute. For example, PowerShell has the Invoke-Expression cmdlet. This cmdlet essentially "converts" a "non-expression" like a string to an expression. The string write-output 'foo' won't do anything at all even though it looks like it will but if that's passed to Invoke-Expression, PowerShell would run the code as you'd expect.

PS> Invoke-Expression -Command "write-output 'foo'"
foo
 

Now that I've got your mind around expressions, let's take it back to scriptblocks. Creating a scriptblock is as simple as enclosing some code in curly braces.

PS> $myscriptblock = { 1 + 1 }
PS> $myscriptblock.GetType().FullName
System.Management.Automation.ScriptBlock

Once you have that code in a scriptblock, it can be executed a few different ways. Two ways are by using the call operator and the Invoke-Command cmdlet as shown below.

PS> & $myscriptblock
2
PS> Invoke-Command -ScriptBlock $myscriptblock
2
PS>

Scriptblocks are also similar to functions. In fact, they sometimes referred to as anonymous functions. We can create a param block just like a function and pass the value for each parameter as positional parameters.

Also notice we can pass parameter arguments to the scriptblock by using the ArgumentList parameter too.

PS> $myscriptblock = { param($Number) 1 + $Number }
PS> & $myscriptblock 3
3
PS> Invoke-Command -ScriptBlock $myscriptblock -ArgumentList 3
3

Now that you know how to create and execute scriptblocks, let's now go into how variables work inside them. As you'll see, they aren't quite as intuitive as you might think.

Variables will naturally expand as you'd expect in scriptblocks.

PS> $variable = 'foo'
PS> $myscriptblock = { "$variable bar" }
PS> & $myscriptblock

However, there are circumstances where this will not work as you'd expect in certain scoping conditions around functions. You'll occasionally have the need to expand the variable in a string and then convert that expression to a scriptblock as shown below. Here I'm calling the Create() method on the scriptblock class to create a scriptblock from the string $variable bar.

$myscriptblock = [scriptblock]::Create("$variable bar")

Another trick to variables and scriptblocks is variable scoping. For example, if I set a variable's value outside of the scriptblock, create a scriptblock with that variable inside, you'll see that is it by reference. When the variable's value is changed outside of the scriptblock, it is changed inside of the scriptblock as well.

PS> $i = 2
PS> $scriptblock = { "Value of i is $i" }
PS> $i = 3
PS> & $scriptblock
Value of i is 3

Enhance your IT career by learning how to automate with Python. Get started  with this free Python guide.

If you need to ensure the variable's value is set static inside of the scriptblock, you'll need force PowerShell to create a copy of the scriptblock by running the GetNewClosure() method on the scriptblock. This forces a new copy which then sets the variable's value inside.

PS> $i = 2
PS> $scriptblock = { "Value of i is $i" }.GetNewClosure()
PS> $i = 3
PS> & $scriptblock
Value of i is 2

That's it for scriptblocks! I hope you've picked up a few pointers on how scriptblocks work and can make your PowerShell scripts a little bit better.

 

Related Posts


Comments
Comments are disabled in preview mode.
Loading animation