PowerShell CTP 3 is Released !

Merry Christmas from the PowerShell Team!

http://blogs.msdn.com/powershell/

Selected New and Updated Features in Windows PowerShell V2 CTP3
(Please refer to Release Notes and Help topics for more details)

·  PowerShell Remoting

·  Windows PowerShell Integrated Scripting Environment (ISE)

·  63 New Cmdlets

·  Modules

·  Script Debugging

·  Advanced Functions

·  PowerShell Class API

Customizing Graphical PowerShell/ISE

Graphical PowerShell, also known as the PowerShell Scripting Environment (ISE) can be customized using an object model.

There is a variable called $psISE in the ISE.

   1: PS >$psise | gm | select Name
   2:  
   3: Name                                                                           
   4: ----                                                                           
   5: Equals                                                                         
   6: GetHashCode                                                                    
   7: GetType                                                                        
   8: ToString                                                                       
   9: CurrentOpenedFile                                                              
  10: CurrentOpenedRunspace                                                          
  11: CustomMenu                                                                     
  12: OpenedRunspaces                                                                
  13: Options              

In there we have options, customMenus, and a number of other cool things. Here we can change the Scripting Pane color to “black”

image

In Redmond to work with the PowerShell Team

Last week I had the tremendous privilege of going to Redmond to work on a PowerShell project with the PowerShell team. Two colleagues and I represented  one of several customers that came to the event.

What was so great about this event was that I was able to show the team what I was working on and they got to see how their product is really being used out in the wild. I was able to learn a lot about the new 2.0 features and implement them in my project with guidance from the PowerShell team.

Being able to finally put faces to names was a wonderful treat. The team is awesome. Hands down, it was the best MS event I have ever been to. Granted, I am a complete PowerShell junky, so for me, just being able to meet the team was fantastic.

What struck me most overall was their passion. I have seen Jeffrey talk and I know he cares deeply about his customers. He absolutely wants to make sure that his team is  doing what is best for his customers. But what was so cool was that this passion goes deep throughout the entire team. From development, to test, to documentation, to UI design for ISE…Everyone on the team wants to make it as great as possible for us. These folks really REALLY care about what they are building, and it obviously shows. They have built a phenomenal product.

Needless to say, this was a wonderful opportunity and if anyone has a chance to meet the PS team, I would HIGHLY recommend it. They are great folks!

In Redmond to work with the PowerShell Team

Last week I had the tremendous privilege of going to Redmond to work on a PowerShell project with the PowerShell team. Two colleagues and I represented  one of several customers that came to the event.

What was so great about this event was that I was able to show the team what I was working on and they got to see how their product is really being used out in the wild. I was able to learn a lot about the new 2.0 features and implement them in my project with guidance from the PowerShell team.

Being able to finally put faces to names was a wonderful treat. The team is awesome. Hands down, it was the best MS event I have ever been to. Granted, I am a complete PowerShell junky, so for me, just being able to meet the team was fantastic.

What struck me most overall was their passion. I have seen Jeffrey talk and I know he cares deeply about his customers and wants to make sure what they are doing is the right thing. But what was so cool was that this passion goes deep throughout the entire team. From development, to test, to documentation, to UI design for ISE…Everyone on the team wants to make it as great as possible for us. These folks really REALLY care about what they are building, and it obviously shows. They have built a phenomenal product.

Needless to say, this was a wonderful opportunity and if anyone has a chance to meet the PS team, I would HIGHLY recommend it. They are great folks!

Passing Variables to a Remote PSSession in CTP 3

PowerShell Sessions are what are used to connect to remote computers using PowerShell. There are a bunch of new Cmdlets that use the noun PSSession. One big change from CTP2 to CTP3 is that we are now using PSSessions rather than Runspaces. I think this is great, as most of the ops/admin folks I work with don’t have a clue what a runspace is or why they would need one to connect to a remote computer. Session seems to be a much better noun. I think its right on par with a telnet session or an RDP session. This makes a lot sense from an Admin’s point of view. Anyway, the way we use PSSessions is through the invoke-command Cmdlet. At a very basic level, invoke-command takes two parameters, a ComputerName and a scriptblock to execute on that remote computer as shown in the example below
   1: PS C:> invoke-command -computer win7andys -scriptblock {cat env:computername}
   2: win7andys
   3: PS C:>
I came across a situation where I needed a variable (lets call it $a) that I was using in my local PSSession to be available in my remote PSSession. Let’s try this and see what happens.
   1: PS C:> "Hello $a"
   2: Hello Foo
   3: PS C:> invoke-command -computer win7andys -scriptblock {"Hello $a"}
   4: Hello
Notice that $a was there locally but not when we tried to use it remotely in our scriptblock. Lucky for us, there is a –ArgumentList parameter that we can use with invoke-command. This looks promising.
   1: PS C:> invoke-command -computer win7andys -ArgumentList $a -scriptblock {"Hello $a"}
   2: Hello
   3: PS C:>
Still no dice, but we are close. Turns out we need to declare $a as a parameter in our scriptblock.
   1: PS C:> invoke-command -computer win7andys -Argu $a -scriptblock {param ($a) "Hello $a"}
   2: Hello Foo
   3: PS C:>
And now we have it!

Passing Variables to a Remote PSSession in CTP 3

PowerShell Sessions are what are used to connect to remote computers using PowerShell. There are a bunch of new Cmdlets that use the noun PSSession. One big change from CTP2 to CTP3 is that we are now using PSSessions rather than Runspaces. I think this is great, as most of the ops/admin folks I work with don’t have a clue what a runspace is or why they would need one to connect to a remote computer. Session seems to be a much better noun. I think its right on par with a telnet session or an RDP session. This makes a lot sense from an Admin’s point of view. Anyway, the way we use PSSessions is through the invoke-command Cmdlet. At a very basic level, invoke-command takes two parameters, a ComputerName and a scriptblock to execute on that remote computer as shown in the example below
   1: PS C:\> invoke-command -computer win7andys -scriptblock {cat env:\computername}
   2: win7andys
   3: PS C:\>
I came across a situation where I needed a variable (lets call it $a) that I was using in my local PSSession to be available in my remote PSSession. Let’s try this and see what happens.
   1: PS C:\> "Hello $a"
   2: Hello Foo
   3: PS C:\> invoke-command -computer win7andys -scriptblock {"Hello $a"}
   4: Hello
Notice that $a was there locally but not when we tried to use it remotely in our scriptblock. Lucky for us, there is a –ArgumentList parameter that we can use with invoke-command. This looks promising.
   1: PS C:\> invoke-command -computer win7andys -ArgumentList $a -scriptblock {"Hello $a"}
   2: Hello
   3: PS C:\>
Still no dice, but we are close. Turns out we need to declare $a as a parameter in our scriptblock.
   1: PS C:\> invoke-command -computer win7andys -Argu $a -scriptblock {param ($a) "Hello $a"}
   2: Hello Foo
   3: PS C:\>
And now we have it!

Exporting Functions in PowerShell Modules

Modules in PowerShell, among other things, will allow code to be shared very easily within a community. One of the issues with scripts and dot sourcing right now is that we end up polluting our working session with a lot of variables and functions that we don't really need. These are helper functions and helper variables that are used by larger functions.

Modules solves this problem. You can create a module (Just name a PS1 script to .PSM1) and specify which functions/variables you want to export.

One way to think about this if you have a C# background is public vs private variables or methods in a class. The exported members are analogous to public methods.

You do this with the export-modulemember cmdlet at the end of your module. Notice that I have four distinct function in my module, test.psm1. However, I am only exporting the functions binn and foo. The other two do not show up when I call get-command. Note that when I call bar, it does indeed have access to foo.

image

BTW, cat2 is an alias I use for Lee Holmes' Syntax Highlighting script. Just wait til you see what else Modules can do, especially Module Manifests. With these we can set all kinds of pre-requisites for our scripts, versions, and a number of other things as well.

Exporting Functions in PowerShell Modules

Modules in PowerShell, among other things, will allow code to be shared very easily within a community. One of the issues with scripts and dot sourcing right now is that we end up polluting our working session with a lot of variables and functions that we don't really need. These are helper functions and helper variables that are used by larger functions.

Modules solves this problem. You can create a module (Just name a PS1 script to .PSM1) and specify which functions/variables you want to export.

One way to think about this if you have a C# background is public vs private variables or methods in a class. The exported members are analogous to public methods.

You do this with the export-modulemember cmdlet at the end of your module. Notice that I have four distinct function in my module, test.psm1. However, I am only exporting the functions binn and foo. The other two do not show up when I call get-command. Note that when I call bar, it does indeed have access to foo.

image

BTW, cat2 is an alias I use for Lee Holmes' Syntax Highlighting script. Just wait til you see what else Modules can do, especially Module Manifests. With these we can set all kinds of pre-requisites for our scripts, versions, and a number of other things as well.

ConvertTo-ScriptBlock

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 ConvertTo-ScriptBlock {
   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

UPDATE:

Osin Grehan has meticulously pointed out that the original name of my function, convert-stringToScriptBlock did not adhere to the naming standard for Cmdlets. Note the following examples:

   1: PS C:> gcm convert* -CommandType cmdlet | ft Name
   2:  
   3: Name
   4: ----
   5: ConvertFrom-Csv
   6: ConvertFrom-SecureString
   7: ConvertFrom-StringData
   8: Convert-Path
   9: ConvertTo-Csv
  10: ConvertTo-Html
  11: ConvertTo-SecureString
  12: ConvertTo-Xml

For convert functions, we should use ConvertTo and ConvertFrom as the “verb”. I wanted to point this out and thank Osin because I completely acknowledge that I am guilty as charged and I think it is a BIG DEAL to stick with standards. Consistency is imperative as PS Adoption rates increase.

In my humble opinion, I  say functions should use the standard verbs just like Cmdlets. You can create shortcuts all day long with aliases. This will become even more important with the introduction of Modules and advanced functions

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