Classes in Powershell 5.0

One of the big new features in Powershell 5.0 is classes. You can now define your own classes and create objects based on those custom classes. You can even create your own version of an existing class using inheritance.

In previous version of Powershell it was actually possible to create classes, but you had to write code in other languages like C# or Visual basic and then use that piece of code as the definition of the class. Now this is much easier.

Lets get right into the code. In these examples I will create a class which contains two properties: ComputerName and Domain. Both will be simple strings. Further down I will add some methods to the class and show some examples on how to use those methods.

First lets look at how we had to create classes before Powershell 5.

Create class with C#

# Create class with C sharp
$ComputerTypeCsharp = @”
    public class ComputerCsharp
    {
        public string ComputerName {get; set;}
        public string Domain {get; set;}
    }
“@
Add-Type -TypeDefinition $ComputerTypeCsharp -Language CSharpVersion3

$x1 = New-Object -TypeName ComputerCsharp
$x1.ComputerName = 'Server01'
$x1.Domain = 'domain.com'
$x1 | Get-Member

Create class with Visual Basic

# Create class with Visual Basic
$ComputerTypeVB = @”
    Public Class ComputerVB
        Public ComputerName As String
        Public Domain As String
    End Class
"@
Add-Type -TypeDefinition $ComputerTypeVB -Language VisualBasic

$x2 = New-Object -TypeName ComputerVB
$x2.ComputerName = 'Server01'
$x2.Domain = 'domain.com'
$x2 | Get-Member
Thats fine for simple classes, but when they become more complex its not very easy to read since the whole definition is just one long string with no highlights and syntax which is quite different from Powershell.

PowerShell classes

Now lets create the same class, but with Powershell. The syntax for creating a class is straight forward:
class ComputerPS 
{
    [string] $ComputerName
    [string] $Domain
}
To create an object using this class we can use [ComputerPS]::new() and assign that to a variable. Then add the ComputerName and Domain strings. Pipe the variable to Get-Member for further inspection.
# Create class with Powershell
class ComputerPS 
{
    [string] $ComputerName
    [string] $Domain
}
# Create a new variable based on the class
$x3 = [ComputerPS]::new()
# Add a computername
$x3.ComputerName = 'server01'
# Add a domain name
$x3.Domain = 'domain.com'
# Pipe to Get-Member for inspection
$x3 | Get-Member

PowerShell classes with methods

So now we can add ComputerName and Domain to the object. What if we want to create a method?
Methods are declared like functions within the class. As of the february release of Powershell 5.0, if a method needs to access variables from outside of the method but within the class then you need to add $this before the variable as you can see in the example below. The method added in this example simply merges the strings together to get a fully qualified domain name, but only if ComputerName and Domain contains text.
# Powershell class with overloaded methods
class ComputerPSwithMethodOverload
{
    [string] $ComputerName
    [string] $Domain
    # Create a method to return fully qualified domain name
    [string] GetFQDN() {
        if ($this.ComputerName -ne '' -and $this.Domain -ne ''){
            return "$($this.ComputerName).$($this.Domain)"
        }
    }
}

$x4 = [ComputerPSwithMethodOverload]::new()
$x4.ComputerName = 'server01'
$x4.Domain = 'domain.com'
$x4 | Get-Member
# Call the method to get FQDN
$x4.GetFQDN()

PowerShell classes with overloaded methods

You can also create overloaded methods. An overloaded method is a method with the same name as another method but in a different context, in this case with different parameters. In this way the method can be called either without parameters or with two parameters. Powershell will try to match with the most appropriate method depending on how many parameters you use. In this example I add two parameters so that we can create a FQDN for any servers, not just the ones in the current object.
# Powershell class with overloaded methods
class ComputerPSwithMethodOverload
{
    [string] $ComputerName
    [string] $Domain
    [string] GetFQDN() {
        if ($this.ComputerName -ne '' -and $this.Domain -ne ''){
            return "$($this.ComputerName).$($this.Domain)"
        }
    }
    # Create another method with the same name, but with different parameters
    [string] GetFQDN([string]$ComputerName, [string]$Domain) {
        if ($ComputerName -ne '' -and $Domain -ne ''){
            return "$ComputerName.$Domain"
        }
    }
}

$x4 = [ComputerPSwithMethodOverload]::new()
$x4.ComputerName = 'server01'
$x4.Domain = 'domain.com'
$x4 | Get-Member
# Call first method
$x4.GetFQDN()
# Call second method
$x4.GetFQDN('MyServer','Example.com')

PowerShell class inheritance

There are cases when an existing class is almost what you need, but not exactly. You can then create your own class which is based on an already existing class. You can then add methods, properties or other things to fit your need. Here is an example where I use my previous class and add another overloaded method. The trick here is to add a ":" and then the name of the class you want to inherit from, when creating your new class. In the example below ComputerPSOverload2 inherits from ComputerPSOverload1.
# Class inheritance: 
class ComputerPSOverload1
{
    [string] $ComputerName
    [string] $Domain
    [string] GetFQDN() {
        if ($this.ComputerName -ne '' -and $this.Domain -ne ''){
            return "$($this.ComputerName).$($this.Domain)"
        }
    }
    [string] GetFQDN([string]$ComputerName, [string]$Domain) {
        if ($ComputerName -ne '' -and $Domain -ne ''){
            return "$ComputerName.$Domain"
        }
    }
}
# Create a second class, based on the one above
class ComputerPSOverload2 : ComputerPSOverload1
{
    # Add another overloaded function, with just one parameter
    [string] GetFQDN([string]$prefix) {
        if ($this.ComputerName -ne '' -and $this.Domain -ne ''){
            return "$prefix$($this.ComputerName).$($this.Domain)"
        }
    }
}

$x5 = [ComputerPSOverload2]::new()
$x5.ComputerName = 'server01'
$x5.Domain = 'domain.com'
$x5 | Get-Member
# Try two of the methods
$x5.GetFQDN()
$x5.GetFQDN('http://')
# Check what type the object is, and check the base type
$x5.GetType()

No comments

Post a Comment