How To Design a PowerShell Module
Modules help to make your code easier to move from one place to another.
- By Adam Bertram
One of the features of Window PowerShell is
modules. Introduced in version 2, modules allows you to group like functions
together that make your code modular, easily transportable and shareable. Modules are a great way to begin making your scripts more professional.
Modules are extremely flexible in that they allow you to write whatever you'd
like in them. I could simply create
a module called
AdamModule and just
throw a bunch of random functions in there if I want to. PowerShell doesn't care. The
flexibility is nice but, at the same time, it's important to adhere to what
modules were designed for: groupings of like functions around a central theme.
When you first open up PowerShell you'll find a lot of modules out of the
box. Below is just a small example:
Modules Only Do One Thing
Notice how they're all based around a central theme of
some sort. All functions inside the
only do "stuff" with AD, functions in the
DnsClient module only do
"stuff" that has to do with DNS client behavior. The
DnsClient module will
not contain any functions that do anything with a DNS server or the
ActiveDirectory module won't do anything with DHCP, for example. Those
are their own modules. It's
important to take your cue from these modules and how they're grouped.
Custom Modules Should Build on Default Modules
I wrote an article awhile back for Pluralsight which was
based on writing scripts as building blocks. It's
a well-known strategy in software development to modularize code so that it can
be reused and built upon. The same goes for module design. You should only write
modules that essentially are smaller, more tightly-defined niches of the default
For example, the
module that comes preloaded with PowerShell has seven different cmdlets related
to the Windows event log.
You can do quite a bit with these cmdlets but what if
you're designing a log management project that will require some detailed event
log analysis and management. This project might require functions like
Test-EventLog to ensure the event log is available,
you're making changes to the event log or even perhaps
Write-ProductYLog if the activities those functions are doing are
different enough to warrant different functions. These requirements might mean
you'll need a specific
Do you see how I'm niching down based on existing
cmdlets? I'm building upon existing code.I could do the same for the
ActiveDirectory where I might have an
ActiveDirectorySite module or maybe an
ActiveDirectoryUser module. I'm niching down getting more specific as I go.
Module Functions Should Talk to Each Other
PowerShell has the pipeline for a reason. You can easily
design functions that can pass information back and forth between each of them.
Let's say I built that log management module and have
Move-ProductXLog and Remove-ProductXLog.I
could build these in a way that
doesn't use the pipeline.
$XLogs = Get-Product
XLogMove-ProductXLog -Log $XLogs
Remove-ProductXLog -Log $XLog
However, I could also prevent code duplication and easily pass logs from one to the other.
Get-ProductXLog | Move-ProductXLog | Remove-ProductXLog
The code is more succinct and easily understood.
I hope that these three tips gave you some good ideas when you start to design your next module. If designed right from the start
you'll see that you're code will be more modular, understandable and easily extensible in the long run.
Adam Bertram is an independent consultant, technical writer, trainer and presenter. Adam specializes in consulting and evangelizing all things IT automation mainly focused around Windows PowerShell. Adam is a Microsoft Windows PowerShell MVP, 2015 powershell.org PowerShell hero and has numerous Microsoft IT pro certifications. He is a writer, trainer and presenter and authors IT pro course content for Pluralsight. He is also a regular contributor to numerous print and online publications and presents at various user groups and conferences. You can find Adam at adamtheautomator.com or on Twitter at @adbertram.