PowerShell 5 introduced the concept of classes. This is an exciting new feature that will really help promote code reusability. It seems natural then, that you would want to organize your classes into PowerShell Modules.
It’s not obvious though, how to use a class defined inside a module from outside that module. There are, in fact, three methods available to you.
Let’s say you have a module, MyModule.psm1. In it you’ve defined a class:
class MyClass { [string] $MyString = 'My String Value' [string] GetSomeValue() { return 'Some Value' } }
Simple enough. So how do we get to this masterpiece of class coding? The first technique has us creating a function inside the module. Within that function we return a new instance of the class.
function Get-NewMyClass() { return [MyClass]::new() } # Export the function, which can generate a new instance of the class Export-ModuleMember -Function Get-NewMyClass
Using it simply requires we import the module, then call the function. From there we can access the properties and methods of our function.
# Import our test module Import-Module -Force 'C:\PS\Classes and Modules\mymodule.psm1' # Use the function to generate a new instance of the 'MyClass' class $myClassFunction = Get-NewMyClass # Call a method from it $myClassFunction.GetSomeValue() # Get a property of the class "MyString=$($myClassFunction.MyString)"
Pretty simple and straightforward. This can be a useful method if there are extra checks you wish to do inside the module prior to returning the new instance of the class.
The next method simply has us create a variable within the module, and export that as a module member.
$newClass = [MyClass]::new() Export-ModuleMember -Variable newClass
You’d then use it in your script, just like any other variable:
# The module also has a variable exported from the function # of type MyClass. "NewClass=$($newClass.MyString)" $newClass.GetSomeValue()
With that shown I have to say I really don’t like this method. Primarily it is due to the issue of name collisions. If you have a variable also named $newClass in your script, it will block out the one from the class causing the collison.
The final option is the new using clause. I want to give a shout out to PowerShell MVP Dave Wyatt (blog | twitter) for pointing this one out to me.
As the first line of your script (except for comments, which are allowed before it) you use the syntax “using module” followed the module name, or path to the module.
using module 'C:\PS\Classes and Modules\mymodule.psm1'
Here I hard coded the path to the module since this is a simple demo. If the module had been installed in one of the default locations for modules, such as the WindowsPowerShell\Modules folder in the current users Documents area, you could have omitted the path and just put the name of the module.
After this, you would simply create a new variable from the class and use it normally.
$myClassUsing = [MyClass]::new() # Setting / Getting property $myClassUsing.MyString # Show default property $myClassUsing.MyString = 'ArcaneCode' # Change the value $myClassUsing.MyString # Show the change # Calling a method $myClassUsing.GetSomeValue()
Note that if you had multiple modules you wanted to access the class definitions in, you would simply have multiple lines of “using module”, each line referencing the module you wanted.
using module 'C:\PS\Classes and Modules\mymodule.psm1' using module 'C:\PS\Classes and Modules\anothermodule.psm1'
There you go. Three ways you can access a class definition stored inside a module, externally. Now not only can you create useful, reusable classes, you can also organize them into modules and use them outside the modules.
thanks for sharing!
Thanks!
May I point out another technique:
$myClassUsing = (Get-Module MyModule).Invoke{[MyClass]::new()}