This article will show how dynamic modules can act as objects for Powershell. With this technique, it is possible to create object definitions in Powershell if you want more object orientation for your scripts.
Let's first look at the Manifest file for the dynamic module. The file modasobj.psd1 contains the following:
#Module manifest for module 'modasobj
#Generated by: Tore Aurstad
@{
ModuleVersion = '1.0'
Guid = 'C9B7488B-507C-470C-B93E-6B040A5EF2AC'
Author='Tore Aurstad'
Description='Demonstrates use of modules as objects'
ScriptsToProcess = @('modasobj.ps1')
}
The manifest file will always have the name MODULENAME.psd1, where MODULENAME is the folder name under one of your $env:psmodulepath folders.
As we see, we define the Guid, Author, Description and ModuleVersion. For non-dynamic modules, we specify more properties in the hashtable of our manifest .psd1 file for our Powershell modules. An overview of the manifest properties to set is here:
How to write a module manifest
We define our module as objects definitions in the other file,
modasobj.ps1
function New-Address {
New-Module -AsCustomObject -Name Address {
$House = $null
$Street = $null
$Town = $null
$County = $null
$Country = $null
$PostCode = $null
Export-ModuleMember -Variable *
}
}
function New-Person {
New-Module -AsCustomObject -Name Person {
$Name = $null
$Address = $null
$Occupation = $null
$Age = $null
$NiNo = $null
Export-ModuleMember -Variable *
}
}
Here we see the use of
New-Module cmdlet, followed by the flag -AsCustomObject and the -Name flag followed by the name of the custom object we want to create.
To play around with this object, we can just create a new Person object and set its address to be an Address object. Some output of this follows.
PS C:\users> import-module modasobj -verbose -force
VERBOSE: Loading module from path 'C:\Users\Tore Aurstad\Documents\WindowsPowerShell\Modules\modasobj\modasobj.psd1'.
VERBOSE: Loading module from path 'C:\Users\Tore Aurstad\Documents\WindowsPowerShell\Modules\modasobj\modasobj.ps1'.
VERBOSE: Dot-sourcing the script file 'C:\Users\Tore
Aurstad\Documents\WindowsPowerShell\Modules\modasobj\modasobj.ps1'.
PS C:\users> $me = New-Person
PS C:\users> $me
Address :
Age :
Name :
NiNo :
Occupation :
PS C:\users> $me.Age = 34
PS C:\users> $me.Name = 'Tore Aurstad'
PS C:\users> $me.Occupation = 'System Developer'
PS C:\users> $me.Occupation = 'Systems Developer'
PS C:\users> $me.Address = 'Kyavegen 1 7045 Trondheim'
PS C:\users> $me.Address.Country = 'Norway'
Property 'Country' cannot be found on this object; make sure it exists and is settable.
At line:1 char:1
+ $me.Address.Country = 'Norway'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
PS C:\users> $me.Address.County = 'Sør-Trøndelag'
Property 'County' cannot be found on this object; make sure it exists and is settable.
At line:1 char:1
+ $me.Address.County = 'Sør-Trøndelag'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
PS C:\users> $address = New-Address
PS C:\users> $me.Address = $address
PS C:\users> $address.Country = 'Norway'
PS C:\users> $me
Address : @{Country=Norway; County=; House=; PostCode=; Street=; Town=}
Age : 34
Name : Tore Aurstad
NiNo :
Occupation : Systems Developer
PS C:\users> $address.County = 'Sør-Trøndelag'
PS C:\users> $address.House = '1'
PS C:\users> $address.PostCode = '7045'
PS C:\users> $address.Street = 'Kyavegen'
PS C:\users> $address.Town = 'Trondheim'
PS C:\users> $me
Address : @{Country=Norway; County=Sør-Trøndelag; House=1; PostCode=7045; Street=Kyavegen; Town=Trondheim}
Age : 34
Name : Tore Aurstad
NiNo :
Occupation : Systems Developer
PS C:\users>
PS C:\users> $me.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False PSCustomObject System.Object
PS C:\users> $address.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False PSCustomObject System.Object
PS C:\users> $me | 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()
Address NoteProperty System.Management.Automation.PSCustomObject Address=@{Country=Norway; County=Sør-Trøndelag...
Age NoteProperty System.Int32 Age=34
Name NoteProperty System.String Name=Tore Aurstad
NiNo NoteProperty NiNo=null
Occupation NoteProperty System.String Occupation=Systems Developer
PS C:\users>
As you can see, I had to adjust above the way I was setting $me.Address properties by having to declare a new address object $address and set its properties
to see the changes reflected in the parent object $me. Both objects are of type
PSCustomObject. As we can see, when we pipe our object variable to the cmdlet
Get-Member, we get a nice listing of our members and derived members. This shows how custom objects can be made inline in Powershell. Of course, Powershell can create objects easily with the
New-Object cmdlet and by specifying a library object either in .NET or created by you, but this shows how you don't have to recompile and create an object specification or class, you can have Powershell create for you, with dynamic modules and the -AsCustomObject and -Name flags set inside the function. In addition, you need to use the cmdlet
Export-ModuleMember-Property *, such that your properties are visible for consumers of the dynamic module.
If you want to remove the module again, use:
remove-module modasobj*
Modules are a huge topic and this article shows one of their many ways of being created.