New Features in PowerShell 3.0

MS PowerShell Team blogged about some of the upcoming features in PowerShell 3.0 here.

I think there are some terrific improvements in the syntax that will make PowerShell more consistent or less unpredictable, if you prefer.

In my tests, some of the features are not yet fully working on Windows 7 but once the final release is out, current issues should go away.

Improved Custom PSObject Creation
One of the cool changes is about creating a custom object. It was already improved in Version 2.0 and now it got even better. Here is a common way of creating one:

Powershell 1.0

$MyCustomObject = New Object PSObject
$MyCustomObject | add-member NoteProperty name "Adil"
$MyCustomObject | add-member NoteProperty lastname "Hindistan"

PowerShell 2.0
$MyCustomObject = new-object PSObject -Property @{name="Adil";lastname="Hindistan"}

PowerShell 3.0
$MyCustomObject = [PsCustomObject]@{name="Adil";lastname="Hindistan"}

So basically you are now simply casting 'PsCustomObject' type like any other.

Local Variables with $using
Another feature I liked seeing is about using local variables. I had written a function a while ago to remove an application given its uninstall string. I needed that to remove unwanted VNC installations from an environment.
It goes something like this:
function remove-app {

    ## E.g. $vnc |%{ remove-app $_ '"C:\Program Files\RealVNC\VNC4\unins000.exe" /SILENT' }, where $vnc holds list of machines

    param ($computer="$env:ComputerName",
       [string]$UninstallString   ## Use QuietUninstallString when possible

    $result="Encountered an error, sorry!"
 if (test-connection $computer -count 1) {
     "Pinging $computer successful"
     if ($UninstallString) {

          ## we have to use param and argumentlist in the script block to pass variable to the remote computers

      $result = invoke-command -computer $computer { param($UninstallString);&cmd /c $UninstallString} -ArgumentList $UninstallString

          ## New in PowerShell 3.0:

          ## $result = invoke-command -computer $computer { &cmd /c $using:$UninstallString}



 } else { "Pinging $computer failed"}



You see that invoke-command line over there? I had to use $UninstallString 3 times in that command to pass it to the remove machine. This got much simpler with PowerShell 3.0 with the addition of "$using:" :

$result = invoke-command -computer $computer { &cmd /c $using:$UninstallString}

By the way, I used that function together with another here that returned a list of uninstall strings from the registry:

function get-appsreg {

    param ($computer="$env:ComputerName",



    $result="Encountered an error, sorry!"

 if (test-connection $computer -count 1) {

        if ($product) {

            ## we have to use param and argumentlist in the script block to pass variable to the remote computers

   $result = invoke-command -computer $computer { param($product);get-itemproperty hklm:\software\microsoft\windows\currentversion\uninstall\* |?{$_.DisplayName -match $product}|Select DisplayName,UninstallString,QuietUninstallString } -ArgumentList $product

        } else {   

   $result = invoke-command -computer $computer { get-itemproperty hklm:\software\microsoft\windows\currentversion\uninstall\*,hklm:\software\wow6432node\microsoft\windows\currentversion\uninstall\* |Select DisplayName,UninstallString,QuietUninstallString } -erroraction silentlycontinue

Count and Length
With PowerShell 3.0 "count" and "length" properties are also becoming universal. I.e. even if an object does not have these properties currently, you will be able to use them in the new version.

Similarly, every object is getting 'indexing'. So, using the custom object example above, it will be possible to use the following syntax:

$MyCustomObject[0]   ## returns the object itself. Other indexes return nothing

It does not look useful really but it does improve the consistency!

No comments: