Convert-StringToScriptBlock

Out of the box in PowerShell, you cannot cast a string to a scriptblock.

   1: 81# [scriptblock]"A String that can't be a SB"
   2: Cannot convert value "A String that can't be a SB" to type "System.Management.Automation.ScriptBlock". Error: "Invalid
   3: cast from 'System.String' to 'System.Management.Automation.ScriptBlock'."
   4: At line:1 char:14
   5: + [scriptblock] <<<< "A String that can't be a SB"

This is actually a good thing. To be able to take a string and arbitrarily execute it could definitely be a security risk. However, there are definitely times when you need to do this.

In my case, I am parsing a Windows Sharepoint list that has a set of ScriptBlocks and our code snippets that I need to execute. However, when I pull them from SharePoint, they are strings.

Originally, I was using Invoke-Expression because everything was running locally. But now, with PowerShell remoting becoming available with V2, I wanted to start using invoke-command. Invoke-Expression takes a string for the –command parameter. Invoke-Command takes a ScriptBlock as a –ScriptBlock paramater

Using an old V1 method, you can use the following function to convert a string to a script block.

   1: function Convert-StringToScriptBlock {
   2: param ([string]$string)
   3: $scriptblock = $executioncontext.invokecommand.NewScriptBlock($string)
   4: return $scriptblock
   5: }

Below is a screen shot of using invoke-command with a string vs the scriptblock that we get back from this function.

image

As you  know, Windows 7 (Demoed at PDC) has PowerShell enabled out of the box. Turns out there is a slightly easier way to do this in the new win7 build and it  will very likely be here in CTP3 as well.

There is now a static method in the ScriptBlock class called Create().

image

So we can write a new V2 function (lets make it an advanced function for fun) using this new method.
   1: function Convert-StringToScriptBlock {
   2: param(
   3: [parameter(ValueFromPipeline=$true,Position=0)]
   4: [string]
   5: $string
   6: )
   7: $sb = [scriptblock]::Create($string)
   8: return $sb
   9: }
Now with the ability to specify the [parameter] attribute and pass it in parameters like ValueFromPipeline we can easily pass in our string from the pipeline or directly via the parameter like we did in the V1 version. image
Comments are closed