Working with PowerShell Objects
====
When cmdlets are executed in PowerShell, the output is an Object, as opposed to only returning text.
This provides the ability to store information as properties.
As a result, handling large amounts of data and getting only specific properties is a trivial task.

As a simple example, the following function retrieves information about storage Devices on a Linux or MacOS operating system platform.
This is accomplished by parsing the output of an existing command, *parted -l* in administrative context, and creating an object from the raw text by using the *New-Object* cmdlet.

```PowerShell
Function Get-DiskInfo {
    $disks = sudo parted -l | Select-String "Disk /dev/sd*" -Context 1,0
    $diskinfo = @()
    foreach ($disk in $disks) {
        $diskline1 = $disk.ToString().Split("`n")[0].ToString().Replace('  Model: ','')
        $diskline2 = $disk.ToString().Split("`n")[1].ToString().Replace('> Disk ','')
        $i = New-Object psobject -Property @{'Friendly Name' = $diskline1; Device=$diskline2.Split(': ')[0]; 'Total Size'=$diskline2.Split(':')[1]}
        $diskinfo += $i
    }
    $diskinfo
}
```

Execute the function and store the results as a variable.
Now retrieve the value of the variable.
The results are formatted as a table with the default view.

*Note: in this example, the disks are virtual disks in a Microsoft Azure virtual machine.*

```PowerShell
PS /home/psuser> $d = Get-DiskInfo
[sudo] password for psuser:
PS /home/psuser> $d

Friendly Name            Total Size Device
-------------            ---------- ------
Msft Virtual Disk (scsi)  31.5GB    /dev/sda
Msft Virtual Disk (scsi)  145GB     /dev/sdb

```

Passing the variable down the pipeline to *Get-Member* reveals available methods and properties.
This is because the value of *$d* is not just text output.
The value is actually an array of .Net objects with methods and properties.
The properties include Device, Friendly Name, and Total Size.

```PowerShell
PS /home/psuser> $d | Get-Member


   TypeName: System.Management.Automation.PSCustomObject

Name          MemberType   Definition
----          ----------   ----------
Equals        Method       bool Equals(System.Object obj)
GetHashCode   Method       int GetHashCode()
GetType       Method       type GetType()
ToString      Method       string ToString()
Device        NoteProperty string Device=/dev/sda
Friendly Name NoteProperty string Friendly Name=Msft Virtual Disk (scsi)
Total Size    NoteProperty string Total Size= 31.5GB
```

To confirm, we can call the GetType() method interactively from the console.

```PowerShell
PS /home/psuser> $d.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array
```

To index in to the array and return only specific objects, use the square brackets.

```PowerShell
PS /home/psuser> $d[0]

Friendly Name            Total Size Device
-------------            ---------- ------
Msft Virtual Disk (scsi)  31.5GB    /dev/sda

PS /home/psuser> $d[0].GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    PSCustomObject                           System.Object
```

To return a specific property, the property name can be called interactively from the console.

```PowerShell
PS /home/psuser> $d.Device
/dev/sda
/dev/sdb
```

To output a view of the information other than default, such as a view with only specific properties selected, pass the value to the *Select-Object* cmdlet.

```PowerShell
PS /home/psuser> $d | Select-Object Device, 'Total Size'

Device   Total Size
------   ----------
/dev/sda  31.5GB
/dev/sdb  145GB
```

Finally, the example below demonstrates use of the *ForEach-Object* cmdlet to iterate through the array and manipulate the value of a specific property of each object.
In this case the Total Size property, which was given in Gigabytes, is changed to Megabytes. 
Alternatively, index in to a position in the array as shown below in the third example.

```PowerShell
PS /home/psuser> $d | ForEach-Object 'Total Size'
 31.5GB
 145GB

PS /home/psuser> $d | ForEach-Object {$_.'Total Size' / 1MB}
32256
148480

PS /home/psuser> $d[1].'Total Size' / 1MB
148480
``` 