PowerShell v5: Class Support

This post is based on the September 2014 preview release of WMF 5.0. This is pre-release software, so this information may change.

One of the banner new features in PowerShell v5 is support for real live .NET Framework class creation in Windows PowerShell. The WMF 5.0 download's release notes has some good examples of what classes look  like, but I wanted to briefly set some expectations for the feature, based on my own early experiences.

The primary use case for classes, at this point, is for DSC resources. Rather than creating a special PowerShell module that has specially named functions, live in a specially named folder, and work in a special way - that's a lot of special, which means a lot of room for error - classes provide a more declarative way of creating DSC resources.

But we're a bit ahead of ourselves. What's a class?

In object-oriented programming, a class is a hunk of code that provides a specific interface. Everything in the .NET Framework is a class. When you run Get-Process in PowerShell, for example, you are returning objects of the type System.Diagnostics.Process - or, in other languages, objects of the class System.Diagnostics.Process. Each process is an instance of the class. The class describes all the standardized things that a process can show you (like its name or ID), or that it can do (like terminate). Programmers build the functionality into the class itself.

Classes can have static properties and methods - these are hunks of code that don't require an actual instance of a process. For example, you can start a process without having a process in the first place. The System.Math class in .NET has lots of static members - the static property Pi, for example, contains the numeric value of pi to a certain number of decimal places. The static Abs() method returns the absolute value of a number.

PowerShell classes are designed to provide similar functionality. The trick with PowerShell classes, at least at this stage of their development, is that they don't add their type name to any kind of global namespace. That is, let's say you write a class named My.Cool.Thing, and you save it into a script module named MyCoolThing.psm1. You can't just go into the shell and run New-Object -TypeName My.Cool.Thing to create an instance of the class, because there's nothing in PowerShell (yet) that knows to go look for your script module to find the class. That'll likely change in a future release, but for right now it means classes are kind of limited.

The basic rule is that you can only use a class within the same module that contains the class. That is, the class can only be "seen" from within the module. So, your MyCoolThing.psm1 module might define a class, and then might also define several commands (functions) that use the class - that's legal, and it will work. You still can't use New-Object; instead, you'd instantiate your class by using something like ClassName::new(), calling the static New() method of the class to instantiate it. I expect New-Object will get "hooked up" at some point, but it might not be until some future version of PowerShell.

Anyway, back to DSC.

DSC is a bit unique, because normally you don't load resource modules; the Local Configuration Manager loads them. When you build a DSC resource class, you're forced to provide three methods: Get(), Set(), and Test(). The LCM loads your module, instantiates the class, and then calls the three methods as needed. DSC resources built in this fashion can live in a plain old module .PSM1 file - there's no need to create a DSCResources subfolder, no need to have an empty "root" module, or any of that. So it's a more elegant solution all around. Aside from some structural differences, you code them the same as you always have. v5 still supports the old-style resources, for backward compatibility, but class-based resources are the "way forward." I expect Microsoft will eventually refactor the DSC Resource Kit to be class-based resources, as soon as they get a minute and as soon as v5 is widely adopted.

So most of the "wiring" behind classes has, to this point, been designed to support that DSC use case. In other words, of all the things a PowerShell class will need to do, the team has so far focused mainly on those things that impact DSC. The rest will come later - the release notes use the phrase, "...in this release" a lot, meaning the team understands where the current weaknesses are. "This release" in some cases may simply mean this current preview release, meaning they're targeting more features for v5's final release; in other cases, more features will have to wait for v6 (or whatever) or a later version of PowerShell.

So there's a little rambling on classes and what's presently in PowerShell v5. If you haven't already downloaded the preview and started playing with it, you should; not in production, though. Keep it in a test VM for the time being.

About the Author

Don Jones

Don Jones is a Windows PowerShell MVP, author of several Windows PowerShell books (and other IT books), Co-founder and President/CEO of PowerShell.org, PowerShell columnist for Microsoft TechNet Magazine, PowerShell educator, and designer/author of several Windows PowerShell courses (including Microsoft's). Power to the shell!