SAPIEN PowerShell Studio 2012

Over the next few blog posts I thought I’d present some of the various PowerShell IDE’s on the market. Yes, that’s right, there’s more out there then just the IDE that ships with PowerShell. I thought I’d kick things off with the “Cadillac” of tools, SAPIEN PowerShell Studio 2012.

This by far is the most comprehensive tool of any on the market. It’s key selling point is the ability to quickly and easily create Windows Forms that can be called from, and raise events in, your PowerShell scripts.

OK, I can already hear you. “Hey Robert this is supposed to be scripts, what do we need Windows Forms for?” That’s a great question.

A very common task to do in scripting is the creation of virtual machines. You can imagine though all of the things you would need to enter in order to create the machine. What’s the name? What’s the activation key? What do you want installed? SQL Server? SharePoint?

You could, of course, have the script prompt you one question at a time. Or have a vast array of command line switches and parameters you need to enter just right in order to run the script. You could reduce complexity by having multiple scripts, but then you increase the workload. Then there’s the issue of who is going to run the script.

It would be far preferable to have a simple, single windows dialog pop up and ask all these questions at once. The person running the script could enter the information in any order, and when they were done just click an big OK button to launch the script.

This also expands the sphere of people who can run the script. Now you will be able to let an experienced PowerShell developer create the complex script, then give it to someone who may not even know PowerShell. They just run a single command, enter in some information into an easy to understand Windows Form, and they are off and running.

But Windows Forms are just the tip of the iceberg. For example, PowerShell Studio makes it easy to package your scripts into executables. Yep, you can take all your proprietary code and keep it safe from prying eyes by compiling it into an easy to distribute EXE file. 

It also has the ability to run your scripts in either 32 or 64 bit mode, all within the same editor. Very nice if you are having to support older systems as well as more modern ones.

From a development standpoint, it has the nice feature of organizing your scripts into projects. This makes management of them much easier.

It has an outstanding editor, with a great help system, and a snippet library loaded up with snippet goodness. The object browser is one of my favorite features. Using it you can drill down into not only PowerShell objects, but .Net, WMI, the file system, and even databases. I find this incredibly useful, I can quickly lookup info without having to leave my IDE.

I will admit that at $349 (as I write this), it’s not the cheapest of the PowerShell IDE’s on the market. However I’m a firm believer in “you get what you pay for”. This price is low enough that it should be a no brainer for any sized company, from a huge multinational corporation to a single person consultant. By taking advantage of the features in SAPIEN’s PowerShell Studio 2012 you’ll recap that back in a very short time.

Without a doubt this is the most feature rich PowerShell IDE I’ve seen. It seems to have everything but the kitchen sink. And I wouldn’t be surprised if that’s in there too and I just haven’t found it yet.

PowerShell v3 Auto Loading of Modules

Modules are the main way to extend functionality in PowerShell. In v2, if you wanted to access the functionality of a module you had to explicitly load it, using the Import-Module functionality. Starting with v3, if PowerShell encounters a command it doesn’t recognize it will go through the list of valid modules looking for that command, and if found load it automatically. Let’s take a look at an example.

First, let’s see what modules are already loaded.

    Get-Module                      # Show modules loaded
ModuleType Name                                ExportedCommands                                                                                            
---------- ----                                ----------------                                                                                            
Manifest   Microsoft.PowerShell.Management     {Add-Computer, Add-Content, Checkpoint-Computer, Clear-Content...}                                          
Manifest   Microsoft.PowerShell.Utility        {Add-Member, Add-Type, Clear-Variable, Compare-Object...}                                                   

Next, let’s see what’s available.

    Get-Module -ListAvailable       # Show what's available to load
    Directory: C:\Users\rcain\Documents\WindowsPowerShell\Modules

ModuleType Name                                ExportedCommands                     
---------- ----                                ----------------                     
Script     adoLib                              {New-Connection, new-sqlcommand, i...
Script     Agent                               {Get-SqlConnection, Get-SqlServer,...
Script     ISECreamBasic                       {Add-IseMenu, Remove-IseMenu}        
Script     mySQLLib                            {New-MySQLConnection, new-MySqlCom...
Script     OracleClient                        {new-oracle_connection, invoke-ora...
Script     OracleIse                           {Connect-Oracle, Disconnect-Oracle...
Script     PBM                                 {Get-PolicyStore, Get-TargetServer...
Script     PerfCounters                        {Invoke-Sqlcmd2, Get-ProcessPerfco...
Script     Repl                                {Get-SqlConnection, Get-ReplServer...
Script     ShowMbrs                            {New-ShowMbrs, Set-ShowMbrs, Get-G...
Script     SQLIse                              {Test-SqlScript, Out-SqlScript, In...
Script     SQLMaint                            {Invoke-DBMaint, Get-SqlConnection...
Binary     SQLParser                           {Test-SqlScript, Out-SqlScript}      
Script     SQLProfiler                         {Invoke-Sqlcmd2, Save-InfoToSQLTab...
Script     SQLPSX                                                                   
Script     SQLServer                           {Get-SqlConnection, Get-SqlServer,...
Script     SSIS                                {New-ISApplication, Copy-ISItemSQL...
Script     WPK                                 {Add-CodeGenerationRule, ConvertFr...

    Directory: C:\Windows\system32\WindowsPowerShell\v1.0\Modules

ModuleType Name                                ExportedCommands                     
---------- ----                                ----------------                     
Manifest   AppLocker                           {Set-AppLockerPolicy, Get-AppLocke...
Manifest   BitsTransfer                        {Add-BitsFile, Remove-BitsTransfer...
Manifest   CimCmdlets                          {Get-CimAssociatedInstance, Get-Ci...
Manifest   Microsoft.PowerShell.Diagnostics    {Get-WinEvent, Get-Counter, Import...
Manifest   Microsoft.PowerShell.Host           {Start-Transcript, Stop-Transcript}  
Manifest   Microsoft.PowerShell.Management     {Add-Content, Clear-Content, Clear...
Manifest   Microsoft.PowerShell.Security       {Get-Acl, Set-Acl, Get-PfxCertific...
Manifest   Microsoft.PowerShell.Utility        {Format-List, Format-Custom, Forma...
Manifest   Microsoft.WSMan.Management          {Disable-WSManCredSSP, Enable-WSMa...
Manifest   PSDiagnostics                       {Disable-PSTrace, Disable-PSWSManC...
Binary     PSScheduledJob                      {New-JobTrigger, Add-JobTrigger, R...
Manifest   PSWorkflow                          New-PSWorkflowExecutionOption        
Manifest   TroubleshootingPack                 {Get-TroubleshootingPack, Invoke-T...

The CIM cmdlets are a new set that ships with v3. Looking at the output above, you’ll note the CIM module (CimCmdlets, highlighted in second set of modules) is not loaded. Let’s run one of the cmdlets from the module.

    # Note the CimCmdlets module isn't loaded. 
    # Now run a command from that module
    Get-CimInstance win32_bios
SMBIOSBIOSVersion : 8DET50WW (1.20 )
Manufacturer      : LENOVO
Name              : Default System BIOS
SerialNumber      : XXXXXXXX
Version           : LENOVO - 1200

Now let’s run Get-Module again, and you’ll see that the module has now been loaded. Pretty slick.

    # Run again to show CimCmdlets is now loaded
ModuleType Name                                ExportedCommands                     
---------- ----                                ----------------                     
Binary     CimCmdlets                          {Get-CimAssociatedInstance, Get-Ci...
Manifest   Microsoft.PowerShell.Management     {Add-Computer, Add-Content, Checkp...
Manifest   Microsoft.PowerShell.Utility        {Add-Member, Add-Type, Clear-Varia...

Of course this does have some drawbacks. First, it will take time for PowerShell to search through all the paths looking for the commands. Second, if the requested module isn’t in one of the predefined path, it will still fail. Finally, just for the sake of self-documentation it’s better to know what modules your script depends on. For that reason when writing scripts or modules of my own I will continue to explicitly use Import-Module, and suggest you do too.

However, when working in interactive mode, i.e. running a PowerShell console and entering commands, auto loading can be a huge timesaver. No longer do I have to take time to issue an Import-Module cmdlet before I can use the commands I need.

Warning: This post was written using PowerShell v3 BETA. Changes between now and the final release may affect the validity of this post.

PowerShell v3 Online Help and Updateable Help

A good help system is important in any language, but especially when it comes to v3 of PowerShell. The number of cmdlets has jumped from around 260 to over 2,300. That’s a lot of new cmdlets to have to learn.

In version 2 syntax, Get-Help accessed the local install to get all of it’s help. And it’s syntax is of course still valid in v3.

  # Get help from the local help files (v2 way, still works in v3)
  Get-Help Get-CimClass

New with version 3 however, is the ability to use Get-Help with the new –Online switch to see the online version of help:

  # You can now pass in the -Online swtich to launch a web browser and
  # see the most recent help in TechNet
  Get-Help Get-CimClass -Online

This will open the default web browser and take you to the MSDN/TechNet entry for the command you are requesting help for. (Note: as I write this v3 is still in Beta, so running the command just takes you to a placeholder web page.)

The other new feature is the ability to update all your local help files dynamically. No longer do you have to wait to install a new release just to get your help updated. The command is very simple:

  # Make sure you are running as an admin!

As the comment says, make sure you are running the PowerShell window in Admin mode. After executing the command wait a few minutes while PowerShell goes online and updates all the local help files. Very nice improvements for keeping your help system up to date.

Warning: This post was written using PowerShell v3 BETA. Changes between now and the final release may affect the validity of this post.

PowerShell v3 -In and–NotIn Operators

Two new operators have been added to PowerShell v3, –In and –NotIn. These are great for folks like me who are used to having this functionality in T-SQL. The syntax is very simple.

    $value = 3
    if ($value -in (1,2,3)) 
      {"The number $value was here"}


The number 3 was here

The not in syntax is just as easy:

    $array = (3,4,5,7)
    if (6 -notin $array) 
      {"6 ain't there"}

Will yield:

6 ain't there

Very simple, but much needed additions to the PowerShell language.

Warning: This post was created using the PowerShell v3 BETA. Changes between now and the final release may affect the validity of this post.

PowerShell v3 Simplified Where-Object Syntax

A great improvement to the new version 3 of PowerShell is the simplification of the Where-Object syntax. Here is an example of the way a Where-Object cmdlet works in v2.

    Set-Location "C:\Windows"  # Just to give us an interesting place
    # Old Syntax
    Get-ChildItem | Where-Object {$_.Length -ge 100kb}

Will produce this output:

Mode                LastWriteTime     Length Name                                                                                                          
----                -------------     ------ ----                                                                                                          
-a---         2/25/2011  12:19 AM    2871808 explorer.exe                                                                                                  
-a---         7/13/2009   8:39 PM     733696 HelpPane.exe                                                                                                  
-a---          6/3/2012   1:10 PM  649849097 MEMORY.DMP                                                                                                    
-a---         7/13/2009   8:39 PM     193536 notepad.exe                                                                                                   
-----         3/15/2012   6:07 AM    2693696 PWMBTHLV.EXE                                                                                                  
-a---         7/13/2009   8:39 PM     427008 regedit.exe                                                                                                   
-a---        12/20/2010   5:11 PM     307712 UltraMon.scr                                                                                                  
-a---         3/21/1996   2:00 PM     284160 uninst.exe                                                                                                    
-a---          6/4/2012   2:04 PM    1134024 WindowsUpdate.log                                                                                             
-a---          3/8/2012   5:37 PM     302448 WLXPGSS.SCR                                                                                                   
-a---         6/10/2009   3:52 PM     316640 WMSysPr9.prx    

Version 3 now allows a simplified version of the cmdlet:

    Get-ChildItem | Where-Object Length -ge 100kb

With v3 you can now eliminate the script block notation (the {} curly braces), the $_ current object placeholder, as well as the . property notation. Now you can simply enter the name of the property and the condition. It produces the same output as what you see above. You can also use it with variables, or with the question mark as an alias for Where-Object.

    $size = 100kb
    Get-ChildItem | Where-Object Length -ge $size
    Get-ChildItem | ? Length -ge 100kb

Please note that this new syntax is only valid for simple where clauses. Anytime you have something more complex, such as multiple conditions, you will be required to revert to the v2 $_ syntax.

Warning: This post was created using the PowerShell v3 BETA. Changes between now and the final release may affect the validity of this post.

PowerShell v3 Ordered HashTables

In version 2 of PowerShell, you could create hashtables, but the order in which the data is stored in the hashtable is not necessarily the same order you input it in. Take this example:

    $hashTableV2 = @{a=1;b=2;c=3;d=4}  

Produces this output:

Name Value

---- -----

  c     3

  d     4

  a     1

  b     2

Version 3 of PowerShell now offers the ability to force the hashtable to hold the data in the same order it was created, using the new [ordered] tag.

    $hashTableV3 = [ordered]@{a=1;b=2;c=3;d=4}  

The new syntax produces this output:

Name Value

---- -----

  a     1

  b     2

  c     3

  d     4

Now if it’s important that your hashtable is in a specific order, you have the [ordered] to make that happen.

Warning: This post was created using PowerShell v3 BETA. Changes to the final version may alter the validity of this post.

PowerShell, Atlanta Techstravaganza, and reading the RSS Feed with PowerShell

Today I had the pleasure of co-presenting “What’s new in Windows 8 PowerShell” (aka PowerShell v3) with my friend, Microsoft Regional Developer Evangelist Glen Gordon (blog | twitter).

You can find the slide deck for our presentation here.

We had a lot of code demos in the presentation, and some due to the short time period we didn’t get to. I’ll be posting the demos over the next few weeks, doing it slowly so as not to overwhelm anyone.

Below is the code to pull the RSS feed for the PowerScripting podcast. The code is pretty self explanatory, see the comments for more info.

#region Reading RSS Feeds

  # Reading RSS Feeds
    # Reading RSS Feeds has become even easier in v3
    $url = ""
    # v2 Syntax
    $webClient = New-Object net.webclient
    [xml]$rss = $webClient.DownloadString($url)
    $ |
       Select-Object Title, pubDate, duration  |
    # v3 Syntax
    Invoke-RestMethod $url |
       Select-Object Title, pubDate, duration  |

    # To know the available object names, open the RSS
    # feed and look at the XML tags inside. The ones
    # shown in this example are pretty commong to most feeds.
#endregion Reading RSS Feeds