I recently got curious about PowerShell Classes, and after digging a bit into it, I have to admit: I actually love it!
PowerShell classes allows us to create PowerShell objects, but in a way cooler and faster way! How do we create classes in powershell? what are the new possibilities that powershell classes offfers us? What is actually a Class? a constructor? how do we instantiate a class? Why should I even care about PowerShell classes?
I will answer all of these questions throughout this post, by focusing the content of this article on two main topics:
- The basics of Windows PowerShell classes.
- Which will cover the vocabulary, and how we use these new keywords.
- A practical use case of using PowerShell classes.
- Create a powershell class in order to fetch, or create a active directory computer object.
I will also try to answer the following broader questions I had, ever since I first heard talking about classes;
- Why should we use classes in PowerShell?
- Where is that thin line located that makes us choose from using a regular function to using a Powershell v5 Class?
This post has been written using the PowerShell v5 April 2015 preview. Some of the concepts / topics covered in this post might be subject to change until the final release get published.
PowerShell Classes: A concrete example
The main objective here, is that after reading this blog post, everybody understands a bit more the powershell classes. For that I will I will first cover the basics. The basic vocabulary will be explained (Since not all of us are developpers, and as a Powershell Scripter, we take a big step towards the developpers universe). It seems important for me, to explain the basic vocabulary like that will help us to understand the new concepts. What is a powershell class? instantiation, enums, $this, etc… .but we will try to build something solid that you can actually use in your own test/production environment.
Computer class
We are going to build a “Computer” class together. While going forward in the learning process, we will expand the functionality of our main class.
I will cover the following powershell Class related topics:
- Create a powershell class
- Return an object that contains specified properties
- Create a powershell class constructor
- Instantiate a Powershell class
- Assign values to properties
- Create a powershell class method and check for a variety of things.
At the end of this post, we will have a class that will do get and set properties, return an object with our default properties. To make this example more ‘real’, I will build a class that will gather information from my local Active Directory database. If the computer is not existing, the class will create the computer object in the AD, assign it a set of default properties (new name, owner, description etc.. ) and all of that using PowerShell Classes.
If you are already familiar with concepts and vocabulary such as ‘Instantiation’,’Class’,’Constructors’,’overloards’ etc… You can skip the first part of this article and rush to ‘PowerShell Classes: Introduction‘ where I cover the concepts of PowerShell classes.
Powershell classes: The basic vocabulary
If there is one thing that can be confusing when you start to learn something new, and what will make things way harder if you don’t have it, is defenitly the vocabulary. I think that it is a bit like speaking a foreign language; If you don’t understand the vocabulary, you won’t understand the message.
Same thing here for Powershell classes. If you don’t know the meaning of the words that are used to describe some technical elements, you won’t be able to fully understand the concepts of it.
Using classes in PowerShell is another step forward towards the developer’s world for IT Pro’s, System engineers and System admins (Did someone say “Devops”?) . This means that a lot of developer concepts, and there related vocabulary are becoming a part of our world.
Powershell Classes really makes us jump this gap, and embrace this other world. I see this as a concret example of Devops in action.
Powershell classes: What is a powershell class?
What is a powershell class actually? before even starting to talk about code, let’s take a short minute and focus on the concept of classes.
A class, would be a ‘Blue Print‘ of a specefic object. For example, in the Active Directory environment, there must be a Class called user, that defines what the object “User” must look like. We can logically think of properties like: Name, surname, address, LoginID, phone number, Managed by, memberof, password etc… Each time we create a new user in active directory, we use the same pattern, and the same manadatory parameters. Once all the required properties are given, we have our new user (thus our ‘new object’) that is created.
Using a class, ensure us to use always the same pattern to create our object, and always returns an object.
If we compare this behaviour to a regular function, we can already see one big difference: The Function does not have to return an object.
Remember this: A class, is a blue print for a specefic object.
powershell class Properties
A property would be an information concerning a specific subject.
A red house.
Red would be a property of the house.
In dotnotation, we would access the house coulor like this –> $House.color
PowerShell wise we use properties ALL the TIME (Even without using classes). When you query for a computer in you active directory using Get-ADComputer, you get an object containing properties. Querying WMI? An object with properties is returned. Querying ConfigMgr information, objects with properties again.
powershell class Methods
A method would be an action that the house would do.
For example OpenGarageDoor would be the action of opening the garage door.
Another example would be “RepaintHouse“, which would for example, change the house color property.
To access a method, we would do the following:
$House.OpenGarageDoor()
We could repaint the house in pink using the following dotnet notation.
$House.RepaintHouse(“Pink“).
If you have worked with WMI and powershell before, you have most likley already have used methods like .Set .put() or Update().
powershell class instantiation
A powershell class works actually just like powershell Objects. They need to be present somewhere in memory. The intiantiation of a class, would be the action of putting a new copy of that class into memory.
If we continue with out house example. Let’s say you already have a house ($House). But you really love the mountains, and the fresh and cold air when you are snowboarding down the hils in the French Alpes, and for that reason, you decide to buy second house at the mountains. A winter house.
Your new winter house, has the same ‘features’ (read attributes) as your main house. It has a color, and a garage door. Once you bought it, you can say that you instanciated your new WinterHouse, and it comes with a default color, and the ability to open the garage door (When there is not 2m of snow in front it;)).
The very basic of a powershell class instantion would be as follow:
1
|
$WinterHouse = [House]::New()
|
powershell class Void
Void is concept that has never really been used in PowerShell until now. Void is used for methods. Generally, you want your methods to return something. A value for example. In some cases, you don’t care about that. You just want you method to do something, and don’t expect anything to come back from it.
For example, when you open the garage door from your house, you want it to open. That’s it. You don’t necessary need a voice going off in the background saying ‘Your door is now open’ like in the old scify movies.
Void in french, would be “rien/vide”
Void in German would be “Leer”
powershell class constructor
A powershell class constructor is the portion of the code that influence how you instantiate a powershell class. If we continue with the House example, we could have multiple ways to build our house.
Let’s say, we have a specefic way to construct a WinterHouse, which will need to be warm, well isolated, with a fire place etc.. and another way to construct a SummerHouse, which will have a garden, pool, fruit trees etc… But both of them will share some elemental properties such as “Roof”, numberOfWindows, Garage, color… and for example have the same OpenGarageDoor() method to open the garage.
You can build more or less the same house, but in two different ways to ‘construct’ it.
It will make more sense a bit later when you see the practical example.
Powershell classes: Introduction
How to create a powershell class?
You can create a very basic empty class as follow:
1
2
3
|
Class Computer {
}
|
Even though you won’t do much with this class like as it is, but this is the very basic stuff you need to have in order to create a class.
You might see the resemblance with a Function, workflow, or Configuration if you are already used to PowerShell. The Keyword syntax that you must use quite often by now. You can actually rely on your existing powershell knowledge gained through the years and put a lot of these concepts in use while writing powershell classes. PowerShell classes is just another building bloc on top of the existing PowerShell concepts.
Adding properties to a PowerShell class
You can add properties to a powershell class as follow:
1
2
3
4
5
6
|
Class Computer {
[String]$Name
[String]$Description
[String]$Type
[String]$Owner
}
|
Every computer that you know has attributes. You generally give it a name, a description, what type of a machine it is, who’s computer is it (owner).
Instantiating a PowerShell class
Now that you have added your first properties to your default class, you would like to see the results. Just to be sure that it actually works. For that we need to bring in that new concept of instanciation.
Instantiating a powershell class, is as I mentioned earlier, the action of putting a new copy in memory of our original object (Remember the new $WinterHouse in the French alps). If we continue with out “Computer Class” example, and let’s say, I just bought my self my very first and brand new computer. I will instantiate my Computer class using the following syntax:
1
|
$NewComputer = [Computer]::New()
|
if we take a look into our variable $NewComputer, we will have an empt object returned with our 4 basic properties.
In the ‘old’ powershell 2/3/4 way (which is not the wrong way) I would written it like this:
12 $Properties = @{Name=”;Description=”;Type=”;Owner=”}$NewComputer = New-Object -type psobject -property $Properties
Adding methods to a PowerShell class
Our computer can do a lot of things. We can Turn it on, turn it off, reboot it etc… If a computer reboots, we might want to keep that information stored somewhere, just to be able to identify a machine that reboots a lot.
Let’s add a new property that will contain the total number of reboots of the computer and I will name it ‘$Reboots’
This is what the class will look like with that new method.
1
2
3
4
5
6
7
8
9
10
11
12
|
Class Computer {
[String]$Name
[String]$Description
[String]$Type
[String]$Owner
[int]$Reboots
[void]Reboot(){
$this.Reboots ++
}
}
|
If we instantiate a new computer assign it to a variable $NewComputer and make it reboot by using the $NewComputer.Reboot() method, we will have the following:
Notice how I have used $This.Reboots++ to increment the $Reboots variable. Basically, $This referes to a variable that has been declared at the begining of the PowerShell class.
Adding values to our properties
Now that we have instantiated our Computer Class into the $NewComputer value, and rebooted it once, we can actually go and set the rest of the properties by using the dot notation.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
Class Computer {
[String]$Name
[String]$Description
[String]$Type
[String]$Owner
[int]$Reboots
[void]Reboot(){
$this.Reboots ++
}
}
$NewComputer = [Computer]::new()
$NewComputer.Name = ‘DC01’
$NewComputer.Description = ‘Domain Controller of Basel Site’
$NewComputer.Type = ‘Server’
$NewComputer.Owner = ‘Stephane van Gulick’
|
If we take a look at our $NEwComputerVariable, this is what it will look like:
PS C:WINDOWSsystem32> $NewComputer
Name : DC01
Description : Domain Controller of Basel Site
Type : Server
Owner : Stephane van Gulick
Reboots : 1
Powershell class constructors
It is nice to be able able to work with objects in PowerShell, but needing to instantiate the class first and assign it to a variable, setting all the properties values afterwards is a bit too much effort. We can make the things easier and more straight forward when we use ‘powershell class constructors‘ .
We have been instantiating our classes using the [Computer]::new() ‘constructor‘ until now. Writing new constructors in our powershell class will allow us to instantiate our class, the [Computer] class, in a different way. In other words, we will be calling our new::() constructor differently.
Basically, we could instantiate a new powershell class and assign directly values to some of the properties. In the example below, I have build a constructor that accepts 3 properties: $Name, $Description, and $owner
A constructor must always have the same name as the powershell class. In our example, the class is named Computer, and the constructor is also named Computer. We can have several constructors. Each of the powershell class constructor must have the same name, but their parameters will vary in number and / or type.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#PowerShell classes
Class Computer {
[String]$Name
[String]$Type
[string]$Description
[string]$owner
[string]$Model
Computer ([string]$Name,$Description,$Owner){
$this.name =$Name
$this.Description = $Description
$this.owner = $Owner
}
}
$NewComputer = [Computer]::new(‘SRVDC01’,‘First Domain Controller’,‘Stephane van Gulick’)
|
While we write the call to instantiate our class using our new:: constructor, we can see that intelisense has found our constructor.
Finally, this is how we would call our new constructor for the class [computer] and the object that would be returned from it.
Powershell class constructor using overloads
Ok, we have done quite some road until now. But let’s make this class a bit more use full to us, and try to make something that could potentially be used later on.
Instantiating a computer class, and giving it a name a description and a owner is good to get logic behind using the PowerShell classes mecanism. But that code won’t really help us in our environment. Let’s enhance our existing code by adding an extra constructor!
In my environment, I do have quite some servers that are running different services; Sharepoint, Configuration Manager, Active Directory, SQL etc…
To illustrate the utility of build constructors in Windows Powershell, I will add two constructors:
- The first one will be a sort of ‘custom‘ Get-AdComputer, that will fit gather information out of active directory when I call my Constructor with only one parameter ($Name). The powershell constructor will gather information from AD, and tailor the object that is returned to fit our corporate standards.
- The second powershell class constructor will be use to create a new computer. It will automaticall provision a Computer object in the AD, and fill it with specific data ($Name, $Description,$Owner) and calculate some specific data ($Type).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
#PowerShell classes
#Creat objects
Class Computer {
[String]$Name
[String]$Type
[string]$Description
[string]$owner
[string]$Model
[int]$Reboots
[void]Reboot(){
$this.Reboots ++
}
Computer ([string]$Name){
if ($comp = Get-ADComputer -filter “name -eq ‘$Name'” -Properties * -ErrorAction SilentlyContinue){
$this.name =$Name
$this.Description = $Comp.Description
switch -wildcard ($comp.OperatingSystem){
(‘*Server*’) {$this.Type = ‘Server’;Break}
(‘*workstation*’) {$this.Type = ‘Workstation’}
(‘*Laptop*’) {$this.Type = ‘Laptop’;Break}
default { $this.Type = ‘N/A’}
}
$this.owner = $comp.ManagedBy.Split(‘,’)[0].replace(‘CN=’,”)
}else{
write-verbose “Could Not find $($this.name)”
}
}
Computer ([string]$Name, [String]$type,[string]$Description,[string]$owner,[String]$Model){
if (!($comp = Get-ADComputer -filter “name -eq ‘$Name'” -Properties name)){
if ($user = Get-ADUser -Filter “name -eq ‘$owner'”){
try{
New-ADComputer -Name $Name -Description $Description -ManagedBy $user -ErrorAction Stop
$this.Name = $Name
$this.Type = $type
$this.Description = $Description
$this.owner = $owner
}catch{
$_
}
}else{
write-warning “the user $($Owner) is not existing. Please verify and try again.”
}
}
}
}
|
We can see here that I added a 2 new constructors, which both have the same name as the class, but they different on their parameters:
- $Name
Which does the following:
- Get the name, description and owner of a computer object
- According to the OS, it will set the value of type to either, Server, Laptop, or workstation.
- $Name, $Description, $Owner, and $Model.
Which does the following:
- Check if the AD Computer Name is not already existing.
- Attempt to get the Owner of the Computer by using the “Get-ADUser” powershell cmdlet.
- Creates the AD computer account with the information provided as parameter.
I have voluntarily left the model empty and cover that information in another blog post.
When we will call the new:: constructor, we will have the choice between our two constructors as highlighted in the next screen shot:
We can see on the screen shot above that the intellisense offers us the choice between the two constructors:
- one with one parameter (string Name)
- Another one with five parameters (String Name, String Type, String Description, string Owner, String Model)
Here under is the results of the call to the longest of the constructors. It created a new computer Object, assigned ‘Kung Lao’ as the owner of the object, and returned a object with our different properties.
The concept of creating a second constructor (or more) in a powershell class is called ‘overloading’ a class. Our class [computer] has two overloads.
The end?
So why should we use PowerShell classes?
Basically, you don’t have to, but we saw that we could make things easier by compating everthing in one single class, and from their, either get information concerning a Computer existing in our Active directory, or by creating a new object for it, and returning a workable object with it.
As for the second question, it will be answered in the part 2 of this blog post, when we would have covered what’s rest for us to learn on PowerShell classes and how to create a class in PowerShell.
Stay tuned, and thanks for reading!
#Stephane
Read more about PowerShell Classes
- Official About_Classes help –> About_Classes
- Trevor Sullivan Youtube channel (Good introduction to classes) –> Youtube channel
- [French] Presentation de Fabien dibot et Pascal Sauliere lors de techDays –> link