August 26, 2015

PowerShell - Create Custom Objects

PowerShell allows you to return structured results from a command so that users can easily sort, group, and filter them. You can create Custom Objects with required properties or methods. Lets explore how to create the objects.

There are different methods you can create Custom Objects.

1. Add-Member cmdlet, a cmdlet that allows us to add properties to an object. In this case we’re adding a NoteProperty, giving our property the name Name and a value that represents the Name property.

$object = New-Object System.Object

$object | Add-Member –MemberType NoteProperty –Name Id –Value 1
$object | Add-Member –MemberType NoteProperty –Name Code –Value "I001"
$object | Add-Member –MemberType NoteProperty –Name Name –Value "Laptop"

Write-Output $object

2. You can assign a hash table to the object to quickly create the objects properties. This can be very useful if you have a list of name/value pairs.

$props = @{
Id = 1
Code = 'I001'
Name = 'Laptop'
}
$object = new-object psobject -Property $props

Write-Output $object

3. Or a shorter alternative like this:

$object = [PSCustomObject]@{
Id = 1
Code = 'I001'
Name = 'Laptop'
}

Write-Output $object

4. New-Module with the AsCustomObject parameter creates a custom object.

$object = New-Module -AsCustomObject -ScriptBlock {
[int]$Id=1 
[string]$Code='I001'
[string]$Name='Laptop'
Export-ModuleMember -Variable *
}

Write-Output $object

5. You can using Add-Type to compile C# or other .NET languages, and in this way you can make a real class definition.

Add-Type @"
    using System;
    public class myClass{

        public int Id=0;
        public string Code="";
        public string Name="";

    }
"@

$object = New-Object myClass
$object.Id = 1
$object.Code = "I001"
$object.Name = "Laptop"

Write-Output $object

6. This method is a quick way of gathering data to be manipulated.

$object = "" | select Id, Code, Name
$object.Id = 1
$object.Code = "I001"
$object.Name = "Laptop"

Write-Output $object

References:
https://technet.microsoft.com/en-us/library/ff730946.aspx
http://social.technet.microsoft.com/wiki/contents/articles/7804.powershell-creating-custom-objects.aspx

PowerShell - Pipeline

One of the fundamental concepts in PowerShell is pipeline. It is a series of commands where the output of one becomes the input of the next, like a production assembly in a factory. It allows you to make refinements on output while being passed between the stages. For this you have to put a pipe '|' sign in-between the commands.

Lets start using it:
Get-Process | Sort-Object Name
Here the output of Get-Process command is become input for Sort-Object command which will sort the items by Name.

Lets add one more command Select-Object to the chain and select only desired columns.
Get-Process | Sort-Object Name | Select-Object Id,Name,Desciption

Add command Group-Object for grouping by name
Get-Process | Sort-Object Name | Select-Object Id,Name,Desciption | Group-Object Name | Select-Object Count, Name
 
Now add ConvertTo-Html to get output in HTML format.
Get-Process | Sort-Object Name | Select-Object Id,Name,Desciption | Group-Object Name | Select-Object Count, Name | ConvertTo-Html

Add Out-File to put all this output in HTML file.
Get-Process | Sort-Object Name | Select-Object Id,Name,Desciption | Group-Object Name | Select-Object Count, Name | ConvertTo-Html | Out-File "C:\Test\test.html"

Open file in browser to see the content.
Invoke-Expression "C:\Test\test.html"

You can find a no of commands which can be used with pipeline to produce the results more meaningful.

PowerShell - Functions

The basic structure of a PowerShell function is : the Function keyword follows the name of the function, and after that the PowerShell script in braces.

Lets create a simple function to say 'hello' :
function myFunction { write-host("Hello") }

Call function:
myFunction

Function has default variable $args, which may contains array of values:
function myFunction { write-host("Hello " + $args) }

These both calls work fine
myFunction 'world'
myFunction 'world' ' from Power Shell'


This function looks for if we have any values supplied in $args when called
function CheckArgs {
    If ($args -ne $null)
    {
        "Args passed : $args"
    }
    Else
    {
        "No Args passed."
    }
}

CheckArgs 'test' 'test3'

Caculate the sum of all numbers specified in $args
function sum
{
    $sum = 0;

    foreach ($i in $args)
    {
        $sum += $i
    }

    "Total : $sum"
}
sum 1 2 3

We can also use named variables as parameters.

function Add($p1, $p2)
{
    $p1 + $p2
}
Add 1 7

Functions can have default values of parameters, in case if the function is being called without parameter then the default value will be used.

function Add($p1 = 5, $p2 = 10)
{
    $p1 + $p2
}

Add 2  # you will get 12, i.e. for parameter $p2, the default value 10 will be used.
Add 2 50 # you will get 52

We can use explicitly data types with functions parameters. If we put the wrong type of argument we will get error message.
function Add([int]$p1, [int]$p2)
{
    $p1 + $p2
}
Add 2 10
Add 2 'test'

 Here the first call works as expected, while the second call give you the error:
Add : Cannot process argument transformation on parameter 'p2'. Cannot convert value "test" to type "System.Int32". Error: "Input string was not in a correct format."

August 25, 2015

PowerShell - Arrays and Hash Tables

Arrays
In PowerShell script, the easiest way to create an array is to use comma separator:
$array = 1,2,3,4,5

For sequential numbers you can use a short syntax:
$array = 1..15

In PowerShell arrays, even you can place values with multiple data types.
$array = "PowerShell", "Version", 3.0

Another sysntax to create array is to use @() construct
$array = @(1, "PowerShell", "Version", 3.0)

You can access array member with zero-based index
$array[1]

Even we can use multiple indices separated by comma, in order to get multiple values.
$array[1,2,3]

Add a new item in array:
$array += "new item"

Hash Tables
To create a hash table, we use @{} instead of @(). Key-value pairs will be stored in hash table separated by semi-colons:
$hashTable = @{Id=1; Code="I001"; Name="Laptop"}

Access a key in Hash Table.
$hashTable["Code"]

We can also specify multiple keys to extract multiple values.
$hashTable["Id", "Code"]

Also you can use the key with dot notation
$hashTable.Code

To get all keys/values present in the HashTable
$hashTable.Keys
$hashTable.Values

Add new key in Hash Table
$hashTable["Category"] = "Office Supplies"
or
$hashTable.Add("Category", "Office Supplies")

Remove a key from Hash Table
$hashTable.Remove("Category")

Look for a key in Hash Table
$hashTable.ContainsKey("Category")

PowerShell - Working with XML

PowerShell supports many of the .Net data types, one of the intesresting type is XML document. Lets see how we can use this type to process XML.

We have a string variable with items list xml:
$items = "<items>" +
    "<item code='I001' name='Laptop'/>" +
    "<item code='I002' name='Tablet'/>" +
    "<item code='I003' name='CellPhone'/>" +
    "</items>"

Now define a new variable with xml data type and assign this string to that variable
[xml]$itemsXml = $items

We can check the Xml back in string format.
$itemsXml.items.InnerXml

This will show the items in table format
$itemsXml.items.ChildNodes

It will also allow you even to modify the xml content.
$itemsXml.items.ChildNodes[0].Attributes["name"].InnerText = "Notebook"

Again display the child nodes to see the effect.
$itemsXml.items.ChildNodes

Lets create a new item:

$xmlElement =  $itemsXml.CreateElement("item")
$xmlNodeNew =  $itemsXml.CreateTextNode("item")
$xmlNodeTemp = $xmlElement.AppendChild($xmlNodeNew)

$xmlAttCode = $itemsXml.CreateAttribute("code")
$xmlAttCode.Value = "I004"
$xmlNodeTemp = $xmlElement.Attributes.Append($xmlAttCode)

$xmlAttName = $itemsXml.CreateAttribute("name")
$xmlAttName.Value = "New Item"
$xmlNodeTemp = $xmlElement.Attributes.Append($xmlAttName)

$itemsXml.LastChild.AppendChild($xmlElement);

Query child nodes to see the effect.
$itemsXml.items.ChildNodes