Powershell module initialization Powershell module initialization powershell powershell

Powershell module initialization


It's not clear if you want to run initialization code when a module is loaded (like Perl's BEGIN block) or if you want to create a custom class (which is what "constructor" suggests).

Initialization code in a module is easy. Any code in a module not embedded in a function is executed when the module is imported.

Creating a custom class isn't supported natively in PS. But see: http://psclass.codeplex.com/. You can also write C#, VBScript, etc. and use Add-Type.

Import-module won't work to simulate a class, because you can only have 1 instance of a module with a given name - at best you'd have a singleton class. (BTW, import-module does have a -passthru parameter, which would more or less make your last line of code work - as a singleton. You'd also have to add export-module -variable * -function * to your module code) You could use New-Module to simulate a class though. And you could wrap it in a function named, new-myClass for example.

BTW, if you use the -ASCustomObject parameter you end up with a hashtable, which doesn't support "this" (in words hash table values that are script blocks don't have a built-in way to refer to the hashtable itself). If you use new-module without -AsCustomObject (and potentially use a factory function, for example new-myclass) then you could simulate "this.varInMyModule" with & $myModule $varInMyModule. However if you create a PSCustomObject, using Add-Member, then script method have access to $this and it in general acts a lot more like a typical object with properties and methods.


Modules are really supposed to output cmdlets, not objects. A module should provide a set of related cmdlets. There is a way to send data into the module using Import-Modules's -ArgumentList parameter as show here. You could use the technique to provide a server name for your cmdlets to connect to for example. The PowerCLI module handles that differently using a cmdlet that creates a script scope connection object ($script:connection) that the other cmdlets check for and re-use if it exists similar to this:

#test.psm1$script:myvar = "hi"function Show-MyVar {Write-Host $script:myvar}function Set-MyVar ($Value) {$script:myvar = $Value}#end test.psm1


Using Modules you can export both innate properties and functions, and don't need to run them through add-member or do much acrobatics. Note however that it has some issues if you don't want to export all properties and methods, and while you can initialize properties to an initial value, you CAN'T call an internal function during initialization without doing some akward acrobatics.

But I think what you really want to do is use Classes which are now available in Powershell 5 (they weren't when you posted). I've provided examples of each. Sysops has a decent tutorial on the new classes in 4 parts

Here's the older way before powershell 5.0

# powershell 3.0 and above (I think)$m = new-module -ascustomobject -scriptblock `    {    $person = "Frodo"    function Who        ()        {return $this.person}    function Rename        ($name)        {$this.person = $name}    Export-ModuleMember -Function * -Variable *    }write-host "direct property access: $($m.person)"write-host "method call: $($m.who())"$m.Rename("Shelob")write-host "change test: $($m.who())"

Also you can replicate multiple objects from a template like this:

# powershell 3.0 and above (I think)$template = `    {    $person = "Frodo"    function Who        ()        {return $this.person}    function Rename        ($name)        {$this.person = $name}    Export-ModuleMember -Function * -Variable *    }$me = new-module -ascustomobject -scriptblock $template; $me.Rename("Shelob")$you = new-module -ascustomobject -scriptblock $template"Me: $($me.Who())""You: $($you.Who())"

And in powershell 5 you have actual classes (mostly)

#requires -version 5Class Person    {    hidden [String] $name #not actually private    [string] Who ()        {return $this.name}    [void] Rename ([string] $name)        {$this.name = $name}    # constructors are weird though, you don't specify return type OR explicitly return value.    Person ([String]$name)        {$this.name = $name}    <#    # The above constructor code is secretly converted to this    [Person] New ([string]$name) #note the added return type and renamed to New        {        $this.name = $name        return $this #note that we are returning ourself, you can exploit this to create chained constructors like [person]::New("gandalf").withWizardLevel("White") but I haven't done so here        }    #>    }$me = [Person]::new("Shelob")$you = [Person]::new("Frodo")# $me|gm        # Note that Name doesn't show here# $me.name      # But we can still access it...# $me|gm -Force # Note that Name DOES show here"`n""Me: $($me.who())""You: $($you.who())"$you.Rename("Dinner")"You after we meet: $($you.who())"