Tuesday, April 07, 2009

PowerShell, Getting the Value Out of a ScriptBlock

When you are doing a little advanced scripting and passing scriptblocks around, one of the problems I encountered was how to execute the scriptblock in a pipeline and get the value out of it. Say you want the user to be able to enter a scriptblock and compare your data to the value returned from it – how is that done?

Executing a scriptblock is easy using the &-operator

$sb={"Hello World!"}


You can also use the invoke method -


If you want to have a filtering scriptblock e.g. comparing a value with a scriptblock (not its value), I found it easy and logical to use where(-object) -

$sb={$_.name –like ‘note*’}
dir $env:windir | where $sb
# or
if (dir $env:windir | where $sb) {"Slipped through filter, go on"}

But what if you want to execute it, feeding in values from the pipeline to get new values? (Often you would only send in one value at a time). The answer is foreach(-object) -

dir $env:windir note* | foreach $sb

When can this be useful? In numerous places, I would say. What if you have some getter script, with these arguments -

Get-XXX –dateproperty <property>
–value <value|scriptblock>
filter <scriptblock>


If this case the code is something like (pseudo code) -

get-object | where &$filter| foreach {
if ($value –is [scriptblock]) {
$compareto=$_ | foreach $value
else {
if ($_.$dateproperty –gt $value) {


The user can then either stick it a value or calculate a value using the scriptblock – and that based on the data from the object itself and before the comparison is made -

# Getting files accessed after January 1st
get-xxx–dateproperty lastAccessTime –value ([datetime] "2009-01-01")
# Getting files accessed 90 days after it was modified
get-xxx–dateproperty lastaccesstime –value {$_.lastwritetime.adddays(90)}

The latter example was not possible without parsing a scriptblock.

No comments: