My Technical Notes

Friday, 19 October 2012

Various Techniques for Powershell

Getting History

To get a history of all commands executed within your Powershell sessions do the following:

    Get-History | Select CommandLine > "C:\Temp\script1.ps1"

This is useful because it allows you to interactively build your code, and once you have finished you can use the above command to dump it into a file and then re-run later.

The default number of commands it keeps is 64, to change it, set the $MaximumHistoryCount to something larger.

Executing an anonymous block

Use the & operator followed by the code block and then by the argument:

    PS> & { param($name) Write-Host $name } 'Tahir'

Expression and Variable Expansion in Strings

Double Quoted Strings allow expansion but single quoted strings do not:

    PS> $name = 'Tahir Hassan';
    PS> 'My Name is $name'
    My Name is $name
    PS> "My Name is $name"
    My Name is Tahir Hassan

Therefore it is desirable to use single-quoted strings unless there is a need for expansion.

To expand a section of code, we wrap it in $() (useful for accessing properties):

    PS> $tahir = @{ 'Name' = 'Tahir'; 'BlogUrl' = '' }
    PS> "My name is $( $tahir.Name ) and my blog can be found at $( $tahir.BlogUrl )"
    My name is Tahir and my blog can be found at
    PS> "test $( 'string' )"
    test string

Importing a DLL

Given a $dll_file_path, use the following command:

    Add-Type -Path $dll_file_path
    # OR
    Add-Type -AssemblyName "System.Web" # for .NET DLL's.

Instantiating an Object

Instantiating an existing class

Any object within the System namespace in mscorelib.dll can be instantiated without explicitly providing the "System" namespace before it:

        $date = New-Object DateTime(2009, 01, 01)

However, for any class outside of the System namespace, you have to provide the full namespace:

        $date = New-Object System.Text.StringBuilder(2009, 01, 01)
        # The first argument to New-Object is a string and the rest of the arguments don't have to be in brackets:
        # $date = New-Object "System.Text.StringBuilder" 2009, 01, 01

Since the first argument (the type) is a string, we can use store the namespace of the type in a string:

        $text_ns = "System.Text"
        # $date = New-Object "$text_ns.StringBuilder" 2009, 01, 01
Creating a Hashtable using @{} sytax

To create an hashtable you can use the @{} syntax:

        $tahir = @{ Name = 'Tahir'; BlogUrl = '' }
        $tahir = @{ '"Name' = 'Tahir'; 'BlogUrl' = '' } # quotes around the keys

Notice that we use a semi-colon and not a comma to separate the key-value pairs.

Creating a PSObject with a set of properties:

To do this we use the New-Object 'PSObject' –Property [HashTable]:

        $tahir = New-Object 'PSObject' -Property @{ 'Name' = 'Tahir'; 'BlogUrl' = '' }

Creating an Array

To create a basic array, you can merely list the elements:

    $my_arr = 1, 2, 3, 4, 5

But using this syntax you cannot create an empty list. A better syntax is using the @(...):

    # same as above
    $my_arr = @(1, 2, 3, 4, 5) 
    # empty array
    $my_arr = @() 
    # concatenating two arrays using the + operator.
    $my_arr = @(1, 2, 3) + @(4, 5)

To access one of the elements you use the square bracket notation:


Creating an ArrayList

To create an arraylist, you can cast an array (as above) to an ArrayList:

    $arraylist = [System.Collections.ArrayList]$array

Calling Static Methods

To call a static method, you need to provide the full type name, which includes the namespace. (there is no way round this):

    [System.Int32]::MaxValue # can use [int] instead here.

Getting Help on commands

To get help on a command, say Get-Process, type the following:

    Get-Help Get-Process

Executing a Cmdlet

In PowerShell, merely typing the cmdlet name will execute it:


Notice that in the above code, we do not use brackets after it e.g. Get-Process(), however the cmdlet is still being executed. When assigning the output notice that

In order to take the first element of this, we need to put brackets around Get-Process and use the square bracket notation:


Adding Intellisense through PowerTab

PowerTab is an extension of the PowerShell tab expansion feature. It can be found at CodePlex - PowerTab.

Viewing information using Out-GridView

Piping information to Out-GridView cmdlet will show the information in a GUI:

    dir | Out-GridView

Relational Operations

Inspired by Relational shell programming.


To order or sort by, use the Sort-Object, aliased as sort:

        dir | Sort-Object name
Alternatively we can pass a function to sort (aka "selector"):

        dir | Sort-Object {$_.Name.SubString(0, 1)}
Selecting (aka "Projecting")
Naively Using Select-Object

When naively selecting using the Select-Object:

            dir | Select-Object 'Name', 'Mode'

What happens is that a PSCustomObject is created with the properties selected.

Using Select-Object with a Selector

Apparently, Select-Object is not designed to work with with a selector:

            PS> dir | Select-Object {$_.Name}
            PS> (dir | Select-Object {$_.Name})[0].'$_.Name'

Basically, it returns PSCustomObject's with a $_.Name property. We instead wanted it to return the Name property only. To to this we can still call Select-Object but with the -ExpandProperty option:

            PS> dir | Select-Object -ExpandProperty 'Name'
            PS> (dir | Select-Object -ExpandProperty 'Name')[0]

However this still does not solve the problem of when we want to pass in a selector. For this, we use the Foreach-Object.

Using Foreach-Object for true Selection

To use Foreach-Object (or it's alias %) we pass in a selector:

            PS> dir | Foreach-Object { $_.Name }
Select Top N Elements

To get the first N elements using Powershell

        dir | Select-Object -First 3

We can also skip a certain number of elements:

        dir | Select-Object -Skip 2

Getting Current Path

Use Get-Location:


Executing a string using Call Operator (&)

Use & as follows:

    & "C:\Program Files\Notepad++\notepad++.exe" "my_file.txt"

Customizing Prompt to only show last Directory Name

Stick the following into your $profile file (create it if it does not exist:

function prompt {
  $loc_path = (Get-Location).Path;
  $cur_dir = $loc_path.SubString($loc_path.LastIndexOf('\') + 1);
  $prompt_str = if ($cur_dir -eq "") { $loc_path } else { $cur_dir };
  return "PS: $prompt_str> ";

If it complains that it does not have the permissions to run the start up script then execute the following:

    Set-ExecutionPolicy Unrestricted -Force

Setting Up Alias's for Commonly used Apps

Use Set-Alias to do this:

    Set-Alias notepad++ "C:\Program Files\Notepad++\notepad++.exe"

No comments: