Sunday, May 11, 2014

All about PowerShell ScriptBlock

ScriptBlock is a powerful concept in PowerShell, often misunderstood or not fully exploited. I thought of writing about a generic function “Wait”, since that depends on ScriptBlock, I decided to write about ScriptBlock. In the next blog, I will introduce you to “Wait”. A ScriptBlock is a collection of statements or expressions that can be used as a single unit. It can be saved in a variable, can be passed to function and can be executed remotely. This blog explores some of these aspects of a ScriptBlock.

Basics

ScriptBlock is a collection of statements between “{“ and “}”. It can be saved in a variable and executed using the call operator “&”. The same block can be executed multiple times.

$scriptblock = { "Hello World" }
& $scriptblock
& $scriptblock


Output:

Hello World
Hello World


ScriptBlock with Parameters

ScriptBlock supports param block just like a function.

$scriptBlock = { param ($message) "Hello $message!" }
& $scriptBlock -Message World


Output:

Hello World!


Variable Scoping

Unlike many languages ScriptBlock references variables dynamically as opposed to capturing current variables. Variables are not evaluated when the ScriptBlock is defined, instead it references the latest value of the variable.

$i = 2
$scriptblock = { "Value of i is $i" }
$i = 3
& $scriptblock # ScriptBlock refers to current values which is 3
$i = 4
& $scriptblock # ScriptBlock refers to current values which is 4


Output:

Value of i is 3
Value of i is 4


Behavior of updating a variable inside a ScriptBlock is consistent with rest of PowerShell. (e.g.) updating a variable in the function. Updates are not reflected in the parent scope with the “&” (call) operator, while the “.” (dot) updates the current scope.

$i = 2
$scriptblock = { $i = $i + 1 }
& $scriptblock
$i

. $scriptblock
$i


Output:

2
3


Closure

From Wikipedia, “In programming languages, a closure is a function or reference to a function together with a referencing environment. A closure—unlike a plain function pointer—allows a function to access those non-local variables even when invoked outside its immediate lexical scope.”

PowerShell offers GetNewClosure that returns a ScriptBlock with captured variables. In that sense PowerShell offers best of both worlds. The following code fragment illustrates that.


$i = 2
$scriptblock = { "Value of i is $i" }.GetNewClosure()
$i = 3
& $scriptblock # To capture the vairables use GetNewClosure


The output of the above script is shown below. Note without closure, ScriptBlock would have referenced the updated value 3.

Value of i is 2


ScriptBlock R-Value

If you used static code blocks in other languages like C/C#, you might be surprised to see the behavior of ScriptBlock definition (without assignment). In PowerShell, if the r-value is not assigned to a variable it is spit out to stdout. Let us look at an example “$i=1+2; $i”. In this case the first statement the r-value “1+2” is assigned to a variable $i. In the second statement “$i”, which is the r-value, since it is not assigned to a variable, the value of that is spit out to stdout.

ScriptBlock definition is really a r-value. Just defining a ScriptBlock means, it is a r-value, hence spit out to stdout without executing it. This might be confusing at first, until the concept is understood (certainly I was surprised!). To execute a ScriptBlock you can use the call operator “&”. Following code demonstrates this concept.

PS C:\> { $i = 1+2; $i }
 $i = 1+2; $i

PS C:\> &{ $i = 1+2; $i }
 3

PS C:\> { $i = 1+2; $i }.ToString()
 $i = 1+2; $i


Invoke-Command & Using

As seen before the ScriptBlock variables has dynamic scope. However the behavior with Invoke-Command is different. Since the execution happens in a different session, for efficiency reasons all the variables in the current scope is not copied to the remote session by default. If a variables has to be copied to the session, it has to be explicitly prefixed with “using:”.

#Create a new session
$s = New-PSSession -ComputerName host1 -Credential $cred

$t1 = 1
$sb = { "t1=$t1" }

#invoke the scriptblock locally
& $sb

#invoke the scriptblock remotely
Invoke-Command -Session $s -ScriptBlock $sb

#invoke the scriptblock remotely with 'using'
$sb = { "t1=$using:t1" }
Invoke-Command -Session $s -ScriptBlock $sb

Remove-PSSession $s


Output from the above script:

t1=1
t1=
t1=1


Explore & Enjoy!
/Siva

16 comments:

  1. One addition: inside a PowerShell code block you can define Begin, Process and End code blocks for pipeline processing...

    PS C:\> $codeblock = {
    begin { Write-Output 'Start' }
    process {Write-Output $_ }
    end { Write-Output 'Finished' }
    }
    PS C:\> 1,2,3 | & $codeblock
    Start
    1
    2
    3
    Finished
    PS C:\>

    ReplyDelete
  2. Can I use pipline in scriptblock ? How do that ?

    ReplyDelete
  3. Red color is difficult to read

    ReplyDelete
  4. How to test script blocks , i can see only output when i run script block but i want to debug, could you please pass information how to do that ?

    ReplyDelete
  5. Great and excellent article. I got more knowledge from this article.recognition a lot for sharing this feature with usPython Online Training
    Learn Python Online

    ReplyDelete
  6. • Nice and good article. It is very useful for me to learn and understand easily. Thanks for sharing your valuable information and time. Please keep updatingAzure Online Training Hyderabad

    ReplyDelete
  7. Excellent, simple yet rich explanation -> elegant!

    ReplyDelete

  8. Nuvigil smart drug is the trade name for Armodafinil smart drug and is the enantiopure compound of Modafinil. There are a number of health benefits that the use of Nuvigil smart drug has to offer to its users. So, you can buy Nuvigil online. The use of the smart drug is safe and has no health issues attached to its usage. In the year 2006, the FDA approved the use of generic Nuvigil smart drug to be used to treat a number of mental issues. Buy Nuvigil online as the use of Nuvigil smart drug has long effect when compared to other smart drugs. This is mainly because Armodafinil smart drug has a longer half-life than the other smart drugs. Therefore more and more people are depending on Nuvigil smart drug to carry on their daily routine smoothly.
    Buy Nuvigil online

    ReplyDelete
  9. After all that I have passed I want to give you a recommendation. check this website for a useful tips!

    ReplyDelete
  10. Norton.com/Setup is  best  antivirus available in the market. If you want to protect your system online or locally from any unforeseen events   Norton.com/Setup   is is a must have software in your PC or Mac. 

    ReplyDelete
  11. McAfee.com/Activate Since the world is developing each day with new computerized advances, digital dangers, malware, information, and harming diseases have additionally turned out to be increasingly more progressed with every day. These digital contamination's harm a gadget or documents in different ways. McAfee.com/Activate  follows the concept of refine your system, you don’t need to worry about data loss or system failure because of the malfunctions. McAfee.com/Activate   works finely on every system including android and ios and supports device like, computer, laptops, mobile phones and tablets.

    ReplyDelete
  12. Install your office.com/Setup by downloading now. Microsoft Office applications are a complete package if multiple integrations like Microsoft Office, Microsoft Power Point, Microsoft Excel etc. All of these programs have their own features and speciality and are used in a lot of industries, small organizations and big organizations.

    ReplyDelete